leecode更新

This commit is contained in:
markilue 2023-01-04 13:36:47 +08:00
parent d10746b2f2
commit a768b112ca
6 changed files with 346 additions and 4 deletions

View File

@ -13,7 +13,7 @@ import java.util.*;
* 给你一个整数数组 nums 和一个整数 k 请你返回其中出现频率前 k 高的元素你可以按 任意顺序 返回答案
* @Version: 1.0
*/
public class TopKFrequent {
public class T07_TopKFrequent {
@Test

View File

@ -12,7 +12,7 @@ import java.util.Stack;
*@Author: dingjiawen
*@CreateTime: 2023-01-03 11:27
*@Description:
* TODO 力扣150题 逆波兰表达式求值:
* TODO 二刷力扣150题 逆波兰表达式求值:
* 根据 逆波兰表示法求表达式的值
* 有效的算符包括+-*/每个运算对象可以是整数也可以是另一个逆波兰表达式
* 注意两个整数之间的除法只保留整数部分

View File

@ -10,7 +10,7 @@ import java.util.*;
*@Author: dingjiawen
*@CreateTime: 2023-01-03 12:00
*@Description:
* TODO 力扣239题 滑动窗口最大值:
* TODO 二刷力扣239题 滑动窗口最大值:
* 给你一个整数数组 nums有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧
* 你只可以看到在滑动窗口内的 k个数字滑动窗口每次只向右移动一位
* 返回 滑动窗口中的最大值

View File

@ -0,0 +1,164 @@
package com.markilue.leecode.stackAndDeque.second;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.stackAndDeque.second
*@Author: dingjiawen
*@CreateTime: 2023-01-04 10:21
*@Description:
* TODO 二刷leecode347 前k个高频元素:
* 给你一个整数数组 nums 和一个整数 k 请你返回其中出现频率前 k 高的元素你可以按 任意顺序 返回答案
*@Version: 1.0
*/
public class T07_TopKFrequent {
@Test
public void test(){
int[] nums = {1, 1, 1, 2, 2, 3};
int k = 2;
System.out.println(Arrays.toString(topKFrequent(nums,k)));
}
@Test
public void test2(){
int[] nums = {3,2,3,1,2,4,5,5,6,7,7,8,2,3,1,1,1,10,11,5,6,2,4,7,8,5,6};
int k = 10;
System.out.println(Arrays.toString(topKFrequent(nums,k)));
}
@Test
public void test1(){
int[] nums = {6,0,1,4,9,7,-3,1,-4,-8,4,-7,-3,3,2,-3,9,5,-4,0};
int k = 6;
System.out.println(Arrays.toString(topKFrequent1(nums,k)));
}
/**
* 思路:TopK的本质还是排序后留下前K个,需要记录<num,count>
* 速度击败5.31%内存击败5.6% 23ms
* @param nums
* @param k
* @return
*/
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
int[] result = new int[k];//直接使用数组的问题就是每插一次就要把他后面的往后挪
Arrays.fill(result,Integer.MIN_VALUE);
if(map.size()==k){
int i=0;
for (Integer integer : map.keySet()) {
result[i++]=integer;
}
}else {
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
Integer count = entry.getValue();
//找到第一个小于count的数
int flag = 0;
while (flag < k && map.getOrDefault(result[flag],0) >= count) {
flag++;
}
int temp=flag;
//插入
for (int i = 1; i < k-flag; i++) {
result[k-i] = result[k-i-1];
}
if(temp<k){
//在最后,填入
result[temp] = entry.getKey();
}
}
}
return result;
}
/**
* 思路:TopK的本质还是排序后留下前K个,需要记录<num,count>,使用能排序的优先队列实现
* 时间复杂度O(nlogk) 堆化操作复杂度logk
* 速度击败90.55%内存击败48.40% 12ms
* @param nums
* @param k
* @return
*/
public int[] topKFrequent1(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
// int[] result = new int[k];//直接使用数组的问题就是每插一次就要把他后面的往后挪
PriorityQueue<int[]> deque = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1]==o2[1]?o2[0]-o1[0]:o2[1]-o1[1];
}
});
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
deque.offer(new int[]{entry.getKey(),entry.getValue()});
}
int[] result = new int[k];
for (int i = 0; i < result.length; i++) {
result[i]=deque.poll()[0];
}
return result;
}
/**
* 官方最快时间复杂度降到O(N)
* 速度击败100%内存击败24.45% 1ms
* @param nums
* @param k
* @return
*/
public int[] topKFrequent2(int[] nums, int k) {
int max = Integer.MIN_VALUE,min = Integer.MAX_VALUE;
for(int i : nums){//找出最大最小值
max = (max < i)?i:max;
min = (min > i)?i:min;
}
if(max==min)return new int[]{nums[0]};
int times[] = new int[max-min+1];//定义桶大小
for(int i : nums){
times[i-min]++;//记录各个数出现的次数
}
ArrayList<Integer> count[] = new ArrayList[nums.length];//不同数量对应的数字集合
for(int i = 0; i < times.length; i++){
if(times[i] > 0){
if(count[times[i]] == null){
count[times[i]] = new ArrayList();
}
count[times[i]].add(i+min);//相同次数的加在同一个count[i]这种
}
}
int res[] = new int[k];//答案
for(int i = count.length-1,j = 0; i >=0 && j < k ; i--){
if(count[i] != null){
while(!count[i].isEmpty()){
res[j++] = count[i].remove(count[i].size()-1);
}
}
}
return res;
}
}

View File

@ -18,7 +18,7 @@ import java.util.Stack;
* 给你二叉树的根节点 root 返回它节点值的 前序 遍历
* @Version: 1.0
*/
public class PreOrderTraversal {
public class T01_PreOrderTraversal {
@Test

View File

@ -0,0 +1,178 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import com.markilue.leecode.tree.TreeUtils;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-04 12:40
*@Description:
* TODO 二刷leecode 144 二叉树的前序:
* 给你二叉树的根节点 root 返回它节点值的 前序 遍历
*@Version: 1.0
*/
public class T01_PreOrderTraversal {
@Test
public void test() {
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3,1,2,5,6,7,8,10));
TreeNode root = TreeUtils.structureTree(list, 0);
System.out.println(preorderTraversal2(root));
}
/**
* 思路:递归法
* 速度击败100%内存击败86.86%
*/
List<Integer> result = new ArrayList<>();//记录答案
public List<Integer> preorderTraversal(TreeNode root) {
if (root == null) {
return result;
}
result.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return result;
}
/**
* 思路:stack迭代法
* 速度击败100%内存击败75.97%
* @param root
* @return
*/
public List<Integer> preorderTraversal1(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root==null){
return result;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if(node.right!=null){
stack.push(node.right);
}
if(node.left!=null){
stack.push(node.left);
}
}
return result;
}
/**
* 官方stack迭代法
* @param root
* @return
*/
public List<Integer> preorderTraversal3(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
while (node != null) {
res.add(node.val);
stack.push(node);
node = node.left;
}
node = stack.pop();
node = node.right;
}
return res;
}
/**
* 思路:Morris遍历
* 速度击败100%内存击败75.97%
* @param root
* @return
*/
public List<Integer> preorderTraversal2(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root==null){
return result;
}
while (root!=null){
//找到上一个连接root的点(左子节点的最右节点)然后放心吧root左移
if(root.left!=null){
TreeNode temp=root.left;
while (temp.right!=root&&temp.right!=null){
temp=temp.right;
}
//判断是从什么条件出来的
if(temp.right==null){
//第一次到这,将这与root连接
temp.right=root;
result.add(root.val);//将其加入后就右移
//放心将root右移
root=root.left;
} else if(temp.right==root){
//第二次来这之前的都已经遍历完了
root=root.right;
temp.right=null;//将right置空,防止下次还遍历
}
}else {
//左边遍历完了,将它右移
result.add(root.val);
root=root.right;
}
}
return result;
}
/**
* 官方morris写法
* @param root
* @return
*/
public List<Integer> preorderTraversal4(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
TreeNode p1 = root, p2 = null;
while (p1 != null) {
p2 = p1.left;
if (p2 != null) {
while (p2.right != null && p2.right != p1) {
p2 = p2.right;
}
if (p2.right == null) {
res.add(p1.val);
p2.right = p1;
p1 = p1.left;
continue;//这里continue以后后面就可以把p1 = p1.right;
} else {
p2.right = null;
}
} else {
res.add(p1.val);
}
p1 = p1.right;
}
return res;
}
}