128. 最长连续序列

  1. int res=0;
  2. Set<Integer> set = new HashSet<>();
  3. for(int i=0;i<nums.length;i++){
  4. set.add(nums[i]);
  5. }
  6. for (Integer integer : set) {
  7. int cur=integer;
  8. if(!set.contains(cur-1)){
  9. while (set.contains(cur)){
  10. cur+=1;
  11. }
  12. res=Math.max(res,cur-integer);
  13. }
  14. }
  15. return res;

136. 只出现一次的数字

  1. //异或运算是相同为假,不同为真。比如4^1就是
  2. // 0 1 0 0
  3. // 0 0 0 1
  4. // 0 1 0 1 =5
  5. int res=0;
  6. for(int i=0;i<nums.length;i++){
  7. res^=nums[i];
  8. }
  9. return res;

146. LRU 缓存

  1. class LRUCache {
  2. private LinkedHashMap<Integer,Integer>map=new LinkedHashMap<>();
  3. private int cap;
  4. public LRUCache(int capacity) {
  5. this.cap=capacity;
  6. }
  7. public int get(int key) {
  8. if(map.containsKey(key)){
  9. int value=map.get(key);
  10. flushRecent(key,value);
  11. return value;
  12. }else{
  13. return -1;
  14. }
  15. }
  16. public void put(int key, int value) {
  17. if(map.containsKey(key)){
  18. flushRecent(key,value);
  19. }else{
  20. map.put(key,value);
  21. if(map.size()>cap){
  22. int oldKey = map.keySet().iterator().next();
  23. map.remove(oldKey);
  24. }
  25. }
  26. }
  27. private void flushRecent(int key,int value){
  28. map.remove(key);
  29. map.put(key,value);
  30. }
  31. }

解法二:自定义链表

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. class LRUCache {
  4. private static class ListNode{
  5. ListNode pre;
  6. ListNode next;
  7. int key;
  8. int value;
  9. public ListNode(int key, int value) {
  10. this.key = key;
  11. this.value = value;
  12. }
  13. }
  14. private static class NodeLinkedList{
  15. ListNode head=null;
  16. ListNode tail=null;
  17. public void addNode(ListNode node){
  18. if(head==null){
  19. head=node;
  20. tail=node;
  21. }else{
  22. tail.next=node;
  23. node.pre=tail;
  24. tail=node;
  25. }
  26. }
  27. public void adjustToTail(ListNode node){
  28. if(node==tail){
  29. return;
  30. }else if(head==node){
  31. ListNode next=node.next;
  32. node.next=null;
  33. next.pre=null;
  34. head=next;
  35. }else{
  36. ListNode pre=node.pre;
  37. ListNode next=node.next;
  38. node.pre=null;
  39. node.next=null;
  40. pre.next=next;
  41. next.pre=pre;
  42. }
  43. tail.next=node;
  44. node.pre=tail;
  45. tail=node;
  46. }
  47. public ListNode deleteHead(){
  48. if(head==null){
  49. return null;
  50. }else if(tail==head){
  51. head=null;
  52. tail=null;
  53. return tail;
  54. }else{
  55. ListNode hd=head;
  56. ListNode next=head.next;
  57. head.next=null;
  58. next.pre=null;
  59. head=next;
  60. return hd;
  61. }
  62. }
  63. }
  64. private int cap;
  65. private NodeLinkedList list=new NodeLinkedList();
  66. private Map<Integer,ListNode> map=new HashMap<>();
  67. public LRUCache(int capacity) {
  68. this.cap=capacity;
  69. }
  70. public int get(int key) {
  71. if(!map.containsKey(key)){
  72. return -1;
  73. }else{
  74. ListNode node = map.get(key);
  75. list.adjustToTail(node);
  76. return node.value;
  77. }
  78. }
  79. public void put(int key, int value) {
  80. if(map.containsKey(key)){
  81. ListNode node = map.get(key);
  82. node.value=value;
  83. map.put(key,node);
  84. list.adjustToTail(node);
  85. }else{
  86. ListNode node = new ListNode(key, value);
  87. map.put(key,node);
  88. list.addNode(node);
  89. if(map.size()>cap){
  90. ListNode node1 = list.deleteHead();
  91. map.remove(node1.key);
  92. }
  93. }
  94. }
  95. }

148. 排序链表

  1. public ListNode sortList(ListNode head) {
  2. if(head==null||head.next==null){
  3. return head;
  4. }
  5. ListNode mid = findMid(head);
  6. ListNode midRight=mid.next;
  7. mid.next=null;
  8. ListNode left = sortList(head);
  9. ListNode right = sortList(midRight);
  10. return mergeNode(left,right);
  11. }
  12. private ListNode findMid(ListNode head){
  13. if(head==null||head.next==null){
  14. return head;
  15. }
  16. ListNode fast=head;
  17. ListNode slow=head;
  18. while (fast.next!=null&&fast.next.next!=null){
  19. fast=fast.next.next;
  20. slow=slow.next;
  21. }
  22. return slow;
  23. }
  24. private ListNode mergeNode(ListNode node1,ListNode node2){
  25. ListNode virtualNode = new ListNode(Integer.MIN_VALUE);
  26. ListNode temp=virtualNode;
  27. while (node1!=null&&node2!=null){
  28. if(node1.val<=node2.val){
  29. temp.next=node1;
  30. node1=node1.next;
  31. }else{
  32. temp.next=node2;
  33. node2=node2.next;
  34. }
  35. temp=temp.next;
  36. }
  37. if(node1==null){
  38. temp.next=node2;
  39. }else{
  40. temp.next=node1;
  41. }
  42. return virtualNode.next;
  43. }

152. 乘积最大子数组

  1. int[]maxDp=new int[nums.length];
  2. int[]minDp=new int[nums.length];
  3. maxDp[0]=nums[0];
  4. minDp[0]=nums[0];
  5. int res=nums[0];
  6. for(int i=1;i<nums.length;i++){
  7. maxDp[i]=Math.max(nums[i],Math.max(maxDp[i-1]*nums[i],minDp[i-1]*nums[i]));
  8. minDp[i]=Math.min(nums[i],Math.min(maxDp[i-1]*nums[i],minDp[i-1]*nums[i]));
  9. res=Math.max(res,maxDp[i]);
  10. }
  11. return res;

169. 多数元素

  1. int voter=nums[0];
  2. int voteCount=0;
  3. for(int i=1;i<nums.length;i++){
  4. if(nums[i]==voter){
  5. voteCount++;
  6. }else if(nums[i]!=voter&&voteCount>0){
  7. voteCount--;
  8. }else{
  9. voter=nums[i];
  10. voteCount=0;
  11. }
  12. }
  13. return voter;

207. 课程表(拓扑排序)

image.png

  1. Map<Integer, Integer> map = new HashMap<>();
  2. //用map来保存每个课程的入度。
  3. for(int i=0;i<numCourses;i++){
  4. map.put(i,0);
  5. }
  6. //用map集合来保存先决关系,比如先完成0才能完成1、2。 0->1、2
  7. Map<Integer, List<Integer>>path=new HashMap<>();
  8. for (int[] prerequisite : prerequisites) {
  9. int cur=prerequisite[1];
  10. int next=prerequisite[0];
  11. map.put(next,map.getOrDefault(next,0)+1);
  12. if(!path.containsKey(cur)){
  13. path.put(cur,new ArrayList<>());
  14. }
  15. path.get(cur).add(next);
  16. }
  17. //用queue来取出path中的元素,让入度-1
  18. Deque<Integer>queue=new LinkedList<>();
  19. for (Integer integer : map.keySet()) {
  20. if(map.get(integer)==0){
  21. queue.addLast(integer);
  22. }
  23. }
  24. while (!queue.isEmpty()){
  25. int cur = queue.pollFirst();
  26. if(!path.containsKey(cur)){
  27. continue;
  28. }
  29. for (Integer integer : path.get(cur)) {
  30. map.put(integer,map.getOrDefault(integer,0)-1);
  31. if(map.get(integer)==0){
  32. queue.addLast(integer);
  33. }
  34. }
  35. }
  36. for (Integer integer : map.keySet()) {
  37. if(map.get(integer)!=0){
  38. return false;
  39. }
  40. }
  41. return true;

208. 实现 Trie (前缀树)

  1. class Trie {
  2. //前缀树根节点不保存数据,每个节点都有26个字符数组,在word末尾设置boolean标志位
  3. private TrieNode root=new TrieNode();
  4. class TrieNode{
  5. boolean end;
  6. TrieNode[]tns=new TrieNode[26];
  7. }
  8. public Trie() {
  9. }
  10. public void insert(String word) {
  11. TrieNode temp=root;
  12. for(int i=0;i<word.length();i++){
  13. int location=word.charAt(i)-'a';
  14. if(temp.tns[location]==null){
  15. temp.tns[location]=new TrieNode();
  16. }
  17. temp=temp.tns[location];
  18. }
  19. temp.end=true;
  20. }
  21. public boolean search(String word) {
  22. TrieNode temp=root;
  23. for(int i=0;i<word.length();i++){
  24. int location=word.charAt(i)-'a';
  25. if(temp.tns[location]==null){
  26. return false;
  27. }else{
  28. temp=temp.tns[location];
  29. }
  30. }
  31. return temp.end;
  32. }
  33. public boolean startsWith(String prefix) {
  34. TrieNode temp=root;
  35. for(int i=0;i<prefix.length();i++){
  36. int location=prefix.charAt(i)-'a';
  37. if(temp.tns[location]==null){
  38. return false;
  39. }else{
  40. temp=temp.tns[location];
  41. }
  42. }
  43. return true;
  44. }
  45. }

215. 数组中的第K个最大元素

  1. PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
  2. @Override
  3. public int compare(Integer o1, Integer o2) {
  4. return o2-o1;
  5. }
  6. });
  7. int res=0;
  8. for(int i=0;i<nums.length;i++){
  9. queue.add(nums[i]);
  10. }
  11. while (k>0){
  12. res=queue.poll();
  13. k--;
  14. }
  15. return res;

221. 最大正方形

image.png

  1. int[][]dp=new int[matrix.length][matrix[0].length];
  2. int res=0;
  3. for(int i=0;i<matrix.length;i++){
  4. for(int j=0;j<matrix[0].length;j++){
  5. if(matrix[i][j]=='1'){
  6. dp[i][j]=1;
  7. res=Math.max(res,dp[i][j]);
  8. }
  9. }
  10. }
  11. for(int i=1;i<dp.length;i++){
  12. for(int j=1;j<dp[0].length;j++){
  13. if(dp[i][j]==0){
  14. continue;
  15. }else{
  16. if(dp[i-1][j]>0&&dp[i][j-1]>0&&dp[i-1][j-1]>0){
  17. dp[i][j]=Math.min(dp[i-1][j],Math.min(dp[i][j-1],dp[i-1][j-1]))+1;
  18. res=Math.max(res,dp[i][j]);
  19. }
  20. }
  21. }
  22. }
  23. return res*res;

234. 回文链表

  1. //先寻找链表中间节点
  2. ListNode fast=head;
  3. ListNode slow=head;
  4. while (fast.next!=null&&fast.next.next!=null){
  5. fast=fast.next.next;
  6. slow=slow.next;
  7. }
  8. //如果fast.next=null说明是奇数个节点,否则是偶数个节点
  9. if(fast.next==null){
  10. ListNode last=slow.next;
  11. //反转前半部分的链表
  12. ListNode pre=null;
  13. ListNode temp=head;
  14. while (temp!=slow){
  15. ListNode next=temp.next;
  16. temp.next=pre;
  17. pre=temp;
  18. temp=next;
  19. }
  20. //执行判断的逻辑
  21. while (pre!=null&&last!=null){
  22. if(pre.val!=last.val){
  23. return false;
  24. }
  25. pre=pre.next;
  26. last=last.next;
  27. }
  28. return true;
  29. //如果是偶数个节点的情况
  30. }else{
  31. ListNode last=slow.next;
  32. //反转前半部分的链表
  33. ListNode pre=null;
  34. ListNode temp=head;
  35. while (temp!=last){
  36. ListNode next=temp.next;
  37. temp.next=pre;
  38. pre=temp;
  39. temp=next;
  40. }
  41. //执行判断的逻辑
  42. while (pre!=null&&last!=null){
  43. if(pre.val!=last.val){
  44. return false;
  45. }
  46. pre=pre.next;
  47. last=last.next;
  48. }
  49. return true;

238. 除自身以外数组的乘积

  1. //可以定义两个dp数组,分别保存从左边相乘的数和从右边相乘的数
  2. int[] leftDp=new int[nums.length];
  3. int[] rightDp=new int[nums.length];
  4. int[] res=new int[nums.length];
  5. leftDp[0]=nums[0];
  6. rightDp[rightDp.length-1]=nums[nums.length-1];
  7. for(int i=1;i<leftDp.length;i++){
  8. leftDp[i]=nums[i]*leftDp[i-1];
  9. }
  10. for(int i=rightDp.length-2;i>=0;i--){
  11. rightDp[i]=nums[i]*rightDp[i+1];
  12. }
  13. res[0]=rightDp[1];
  14. res[res.length-1]=leftDp[leftDp.length-2];
  15. for(int i=1;i<res.length-1;i++){
  16. res[i]=leftDp[i-1]*rightDp[i+1];
  17. }
  18. return res;

239. 滑动窗口最大值

  1. int[]res=new int[nums.length-k+1];
  2. Deque<Integer>queue=new LinkedList<>();
  3. int index=0;
  4. for(int i=0;i<nums.length;i++){
  5. //头(清除头部元素)
  6. if(!queue.isEmpty()&&queue.peekFirst()==i-k){
  7. queue.pollFirst();
  8. }
  9. //尾(维持一个单调递增的队列)
  10. while (!queue.isEmpty()&&nums[i]>=nums[queue.peekLast()]){
  11. queue.pollLast();
  12. }
  13. //尾
  14. queue.addLast(i);
  15. //头
  16. if(i>=k-1){
  17. res[index++]=nums[queue.peekFirst()];
  18. }
  19. }
  20. return res;

240. 搜索二维矩阵 II

  1. //从矩阵的左下角入手开始找
  2. int row=matrix.length-1;
  3. int col=0;
  4. while (row>=0&&row<=matrix.length-1&&col>=0&&col<=matrix[0].length-1){
  5. if(target==matrix[row][col]){
  6. return true;
  7. }else if(target>matrix[row][col]){
  8. col++;
  9. }else{
  10. row--;
  11. }
  12. }
  13. return false;

287. 寻找重复数(二分法)

  1. int left=1;
  2. int right=nums.length-1;
  3. while (left<=right){
  4. int count=0;
  5. int mid=(left+right)/2;
  6. for(int i=0;i<nums.length;i++){
  7. if(nums[i]<=mid){
  8. count++;
  9. }
  10. }
  11. if(count<=mid){
  12. left=mid+1;
  13. }else{
  14. right=mid-1;
  15. }
  16. }
  17. return left;

297. 二叉树的序列化与反序列化

  1. public class Codec {
  2. static class TreeNode{
  3. int val;
  4. TreeNode left;
  5. TreeNode right;
  6. public TreeNode(int value) {
  7. this.val = value;
  8. }
  9. public TreeNode() {
  10. }
  11. public TreeNode(int value,TreeNode left,TreeNode right) {
  12. this.val = value;
  13. this.left = left;
  14. this.right = right;
  15. }
  16. }
  17. // Encodes a tree to a single string.
  18. public String serialize(TreeNode root) {
  19. if(root==null){
  20. return null;
  21. }
  22. StringBuilder builder = new StringBuilder();
  23. Deque<TreeNode>queue=new LinkedList<>();
  24. queue.addLast(root);
  25. while (!queue.isEmpty()){
  26. TreeNode node = queue.pollFirst();
  27. if(node!=null) {
  28. builder.append(node.val).append(",");
  29. }else{
  30. builder.append("null").append(",");
  31. continue;
  32. }
  33. queue.addLast(node.left);
  34. queue.addLast(node.right);
  35. }
  36. return builder.toString().substring(0,builder.length()-1);
  37. }
  38. // Decodes your encoded data to tree.
  39. public TreeNode deserialize(String data) {
  40. if(data.equals("null")||data.length()==0){
  41. return null;
  42. }
  43. String[] split = data.split(",");
  44. int index=1;
  45. Deque<TreeNode>queue=new LinkedList<>();
  46. TreeNode root = new TreeNode(Integer.parseInt(split[0]));
  47. queue.addLast(root);
  48. while (!queue.isEmpty()){
  49. TreeNode node = queue.pollFirst();
  50. if(!split[index].equals("null")){
  51. TreeNode left = new TreeNode(Integer.parseInt(split[index]));
  52. node.left=left;
  53. queue.addLast(left);
  54. }
  55. index++;
  56. if(!split[index].equals("null")){
  57. TreeNode right = new TreeNode(Integer.parseInt(split[index]));
  58. node.right=right;
  59. queue.addLast(right);
  60. }
  61. index++;
  62. }
  63. return root;
  64. }
  65. }

300. 最长递增子序列*

  1. int[]dp=new int[nums.length];
  2. Arrays.fill(dp,1);
  3. int res=1;
  4. for(int i=1;i<nums.length;i++){
  5. for(int j=0;j<i;j++){
  6. if(nums[i]>nums[j]){
  7. dp[i]=Math.max(dp[j]+1,dp[i]);
  8. res=Math.max(res,dp[i]);
  9. }
  10. }
  11. }
  12. return res;

301. 删除无效的括号

  1. class Solution {
  2. private StringBuilder builder=new StringBuilder();
  3. private Set<String> set=new HashSet<>();
  4. public List<String> removeInvalidParentheses(String s) {
  5. int leftCount=0;
  6. int rightCount=0;
  7. //这里的逻辑是判断看需要删除多少个左括号、右括号
  8. for(int i=0;i<s.length();i++){
  9. if(s.charAt(i)=='('){
  10. leftCount++;
  11. }else if(s.charAt(i)==')'){
  12. if(leftCount>0){
  13. leftCount--;
  14. }else{
  15. rightCount++;
  16. }
  17. }
  18. }
  19. backTrack(0,s,leftCount,rightCount);
  20. return new ArrayList<>(set);
  21. }
  22. private void backTrack(int index,String s,int left,int right){
  23. if(index==s.length()){
  24. if(left==0&&right==0&&check(builder)){
  25. set.add(builder.toString());
  26. }
  27. return;
  28. }
  29. char c = s.charAt(index);
  30. if(c=='('){
  31. builder.append(c);
  32. backTrack(index+1,s,left,right);
  33. builder.deleteCharAt(builder.length()-1);
  34. if(left>0){
  35. backTrack(index+1,s,left-1,right);
  36. }
  37. }else if(c==')'){
  38. builder.append(c);
  39. backTrack(index+1,s,left,right);
  40. builder.deleteCharAt(builder.length()-1);
  41. if(right>0){
  42. backTrack(index+1,s,left,right-1);
  43. }
  44. }else{
  45. builder.append(c);
  46. backTrack(index+1,s,left,right);
  47. builder.deleteCharAt(builder.length()-1);
  48. }
  49. }
  50. private boolean check(StringBuilder builder){
  51. int left=0;
  52. int right=0;
  53. for(int i=0;i<builder.length();i++){
  54. if(builder.charAt(i)=='('){
  55. left++;
  56. }else if(builder.charAt(i)==')'){
  57. if(left==0){
  58. return false;
  59. }else{
  60. left--;
  61. }
  62. }
  63. }
  64. return left==0;
  65. }
  66. }

338. 比特位计数

  1. int[]dp=new int[n+1];
  2. dp[0]=0;
  3. for(int i=n;i>=1;i--){
  4. int oneCount=0;
  5. int temp=i;
  6. while (temp!=0){
  7. temp&=temp-1;
  8. oneCount++;
  9. }
  10. dp[i]=oneCount;
  11. }
  12. return dp;

347. 前 K 个高频元素

  1. //大顶堆+哈希表
  2. int[]dp=new int[k];
  3. Map<Integer,Integer> map=new HashMap<>();
  4. for(int i=0;i<nums.length;i++){
  5. map.put(nums[i],map.getOrDefault(nums[i],0)+1);
  6. }
  7. PriorityQueue<Map.Entry<Integer,Integer>>queue=new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
  8. @Override
  9. public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
  10. return o2.getValue()-o1.getValue();
  11. }
  12. });
  13. for (Map.Entry<Integer, Integer> integerIntegerEntry : map.entrySet()) {
  14. queue.add(integerIntegerEntry);
  15. }
  16. for(int i=0;i<k;i++){
  17. dp[i]=queue.poll().getKey();
  18. }
  19. return dp;