leecode更新
This commit is contained in:
parent
d10746b2f2
commit
a768b112ca
|
|
@ -13,7 +13,7 @@ import java.util.*;
|
||||||
* 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
|
* 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class TopKFrequent {
|
public class T07_TopKFrequent {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -12,7 +12,7 @@ import java.util.Stack;
|
||||||
*@Author: dingjiawen
|
*@Author: dingjiawen
|
||||||
*@CreateTime: 2023-01-03 11:27
|
*@CreateTime: 2023-01-03 11:27
|
||||||
*@Description:
|
*@Description:
|
||||||
* TODO 力扣150题 逆波兰表达式求值:
|
* TODO 二刷力扣150题 逆波兰表达式求值:
|
||||||
* 根据 逆波兰表示法,求表达式的值。
|
* 根据 逆波兰表示法,求表达式的值。
|
||||||
* 有效的算符包括+、-、*、/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
|
* 有效的算符包括+、-、*、/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
|
||||||
* 注意两个整数之间的除法只保留整数部分。
|
* 注意两个整数之间的除法只保留整数部分。
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import java.util.*;
|
||||||
*@Author: dingjiawen
|
*@Author: dingjiawen
|
||||||
*@CreateTime: 2023-01-03 12:00
|
*@CreateTime: 2023-01-03 12:00
|
||||||
*@Description:
|
*@Description:
|
||||||
* TODO 力扣239题 滑动窗口最大值:
|
* TODO 二刷力扣239题 滑动窗口最大值:
|
||||||
* 给你一个整数数组 nums,有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧。
|
* 给你一个整数数组 nums,有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧。
|
||||||
* 你只可以看到在滑动窗口内的 k个数字。滑动窗口每次只向右移动一位。
|
* 你只可以看到在滑动窗口内的 k个数字。滑动窗口每次只向右移动一位。
|
||||||
* 返回 滑动窗口中的最大值 。
|
* 返回 滑动窗口中的最大值 。
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,7 +18,7 @@ import java.util.Stack;
|
||||||
* 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
|
* 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
|
||||||
* @Version: 1.0
|
* @Version: 1.0
|
||||||
*/
|
*/
|
||||||
public class PreOrderTraversal {
|
public class T01_PreOrderTraversal {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue