本文最后更新于:2 个月前
                  
                
              
            
            
              
                
                
破冰 
这是一个新的系列,该博文原名为 “冲刺蓝桥杯”,是 2023/04/14晚创建的,当时看了黑马阿玮老师的一个视频,有感而发新增的博文,也是我的博客中,最早的一批文章了
🥣 这篇博文长久以来并没有什么内容,原内容我已经保存在最下面的 “前世今生” 栏目中(好中二的栏目,哈哈哈)
🔥 我决定将该博文改造为全新的算法题目实战 相关博文,开启一个全新的系列 
🍖 我将在这篇博文下,给出常见的面试算法题 / 蓝桥杯赛题的题解,持续磨练自己的算法能力
今晚,命运的齿轮开始转动 
🍖 推荐阅读:交换排序—冒泡排序 | 智能后端和架构 (yijiyong.com) 
思维碰撞 
废话少说,直接进入正题
 
力扣算法题打卡 Day 1 
2023年11月10日
 
反转链表 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution  {public  ListNode reverseList (ListNode head)  {ListNode  ans  =  new  ListNode (-1 );ListNode  cur  =  head;while  (cur != null ) {ListNode  next  =  cur.next;return  ans.next;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution  {public  ListNode reverseList (ListNode head)  {ListNode  prev  =  null ;ListNode  curr  =  head;while  (curr != null ) {ListNode  next  =  curr.next;return  prev;
优雅的递归法:(2024/01/22晚) 
1 2 3 4 5 6 7 8 9 10 11 12 class  Solution  {public  ListNode reverseList (ListNode head)  {if (head == null  || head.next == null )return  head;ListNode  last  =   reverseList(head.next);null ;return  last;
合并两个有序链表 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class  Solution  {public  ListNode mergeTwoLists (ListNode list1, ListNode list2)  {ListNode  newHead  =  new  ListNode (-1 );ListNode  res  =  newHead;while  (list1 != null  && list2 != null ) {if  (list1.val < list2.val) {else  if  (list1.val > list2.val) {else  { while  (list1 != null ) {while  (list2 != null ) {return  res.next;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class  Solution  {public  ListNode mergeTwoLists (ListNode list1, ListNode list2)  {ListNode  prehead  =  new  ListNode (-1 );ListNode  prev  =  prehead;while  (list1 != null  && list2 != null ) {if  (list1.val <= list2.val) {else  {null  ? list2 : list1;return  prehead.next;
有效括号 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class  Solution  {public  boolean  isValid (String s)  {if  (s.length() <= 1 ) {return  false ;new  HashMap <>();'(' , ')' );'{' , '}' );'[' , ']' );new  Stack <>();for  (int  i  =  0 ; i < s.length(); i++) {char  item  =  s.charAt(i);if  (smap.containsKey(item)) {else  {if  (stack.isEmpty()) {return  false ;Character  left  =  stack.pop();char  rightChar  =  smap.get(left);if  (rightChar != item) {return  false ;return  stack.isEmpty();
最小栈 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class  MinStack  {private  Stack<Integer> stack;  private  Stack<Integer> minStack;  public  MinStack ()  {new  Stack <>();  new  Stack <>();  public  void  push (int  val)  {if  (minStack.isEmpty() || val <= minStack.peek()) {  public  void  pop ()  {if  (stack.peek().equals(minStack.peek())) {  public  int  top ()  {return  stack.peek();  public  int  getMin ()  {return  minStack.peek();  
力扣算法题打卡 Day 2 
2023年11月11日
 
删除倒数第 K 个节点 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class  Solution  {public  ListNode removeNthFromEnd (ListNode head, int  n)  {ListNode  dummy  =  new  ListNode (0 );ListNode  first  =  head;ListNode  second  =  dummy;for  (int  i  =  0 ; i < n; ++i) {while  (first != null ) {assert  second.next != null ;return  dummy.next;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class  Solution  {public  ListNode removeNthFromEnd (ListNode head, int  n)  {ListNode  dummy  =  new  ListNode (0 );new  LinkedList <ListNode>();ListNode  cur  =  dummy;while  (cur != null ) {for  (int  i  =  0 ; i < n; ++i) {ListNode  prev  =  stack.peek();assert  prev != null ;return  dummy.next;
删除所有重复元素 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class  Solution  {public  ListNode deleteDuplicates (ListNode head)  {if  (head == null ) {return  null ;ListNode  dummy  =  new  ListNode (0 );ListNode  cur  =  dummy;while  (cur.next != null  && cur.next.next != null ) {if  (cur.next.val == cur.next.next.val) {int  x  =  cur.next.val;while  (cur.next != null  && cur.next.val == x) {else  {return  dummy.next;
二叉树层序遍历(分层) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class  Solution  {public  List<List<Integer>> levelOrder (TreeNode root)  {if  (root == null ) {return  new  ArrayList <List<Integer>>();new  ArrayList <List<Integer>>();new  LinkedList <TreeNode>();while  (queue.size() > 0 ) {int  size  =  queue.size();new  ArrayList <Integer>();for  (int  i  =  0 ; i < size; ++i) {TreeNode  t  =  queue.remove();if  (t.left != null ) {if  (t.right != null ) {return  res;
二叉树右视图 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  List<Integer> rightSideView (TreeNode root)  {new  ArrayList <>();if  (root == null ) {return  res;new  LinkedList <>();while  (!queue.isEmpty()) {int  size  =  queue.size();for  (int  i  =  0 ; i < size; i++) {TreeNode  node  =  queue.poll();if  (node.left != null ) {if  (node.right != null ) {if  (i == size - 1 ) {  return  res;
力扣算法题打卡 Day 3 
2023年11月12日
 
两数之和 
1 2 3 4 5 6 7 8 9 10 11 12 13 class  Solution  {public  int [] twoSum(int [] nums, int  target) {new  HashMap <>();for  (int  i  =  0 ; i < nums.length; i++) {if  (map.containsKey(target - nums[i])) {return  new  int []{i, map.get(target - nums[i])};return  new  int [0 ];
区间反转链表 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class  Solution  {public  ListNode reverseBetween (ListNode head, int  left, int  right)  {ListNode  dummyNode  =  new  ListNode (-1 );ListNode  pre  =  dummyNode;for  (int  i  =  0 ; i < left - 1 ; i++) {ListNode  rightNode  =  pre;for  (int  i  =  0 ; i < right - left + 1 ; i++) {ListNode  leftNode  =  pre.next;ListNode  succ  =  rightNode.next;null ;null ;return  dummyNode.next;public  static  ListNode reverseList (ListNode head)  {ListNode  ans  =  new  ListNode (-1 );ListNode  cur  =  head;while  (cur != null ) {ListNode  next  =  cur.next;return  ans.next;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  ListNode reverseBetween (ListNode head, int  left, int  right)  {ListNode  dummyNode  =  new  ListNode (-1 );ListNode  pre  =  dummyNode;for  (int  i  =  0 ; i < left - 1 ; i++) {ListNode  cur  =  pre.next;for  (int  i  =  0 ; i < right - left; i++) {return  dummyNode.next;
链表第一个公共节点 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public  class  Solution  {public  ListNode getIntersectionNode (ListNode pHead1, ListNode pHead2)  {if  (pHead1 == null  || pHead2 == null ) {return  null ;ListNode  p1  =  pHead1;ListNode  p2  =  pHead2;while  (p1 != p2) {if  (p1 != p2) {if  (p1 == null ) {if  (p2 == null ) {return  p1;
更加清晰易懂的解法:(2023/01/22晚) 
1 2 3 4 5 6 7 8 9 10 11 12 13 ListNode getIntersectionNode (ListNode headA, ListNode headB)  {ListNode  p1  =  headA, p2 = headB;while  (p1 != p2) {if  (p1 == null ) p1 = headB;else             p1 = p1.next;if  (p2 == null ) p2 = headA;else             p2 = p2.next;return  p1;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public  class  Solution  {public  ListNode getIntersectionNode (ListNode pHead1, ListNode pHead2)  {if  (pHead1 == null  || pHead2 == null ) {return  null ;ListNode  current1  =  pHead1;ListNode  current2  =  pHead2;new  HashMap <ListNode, Integer>();while  (current1 != null ) {null );while  (current2 != null ) {if  (hashMap.containsKey(current2))return  current2;return  null ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public  class  Solution  {public  ListNode getIntersectionNode (ListNode headA, ListNode headB)  {new  Stack <>();new  Stack <>();while  (headA != null ) {while  (headB != null ) {ListNode  preNode  =  null ;while  (stackB.size() > 0  && stackA.size() > 0 ) {if  (stackA.peek() == stackB.peek()) {else  {break ;return  preNode;
两两交换链表中的节点 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  Solution  {public  ListNode swapPairs (ListNode head)  {ListNode  dummyHead  =  new  ListNode (0 );ListNode  cur  =  dummyHead;while  (cur.next != null  && cur.next.next != null ) {ListNode  node1  =  cur.next;ListNode  node2  =  cur.next.next;return  dummyHead.next;
合并K个有序链表 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class  Solution  {public  ListNode mergeKLists (ListNode[] lists)  {ListNode  res  =  null ;for  (ListNode list : lists) {return  res;public  static  ListNode mergeTwoListsMoreSimple (ListNode l1, ListNode l2)  {ListNode  prehead  =  new  ListNode (-1 );ListNode  prev  =  prehead;while  (l1 != null  && l2 != null ) {if  (l1.val <= l2.val) {else  {null  ? l2 : l1;return  prehead.next;
二叉树锯齿型遍历 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class  Solution  {public  List<List<Integer>> zigzagLevelOrder (TreeNode root)  {new  ArrayList <>();  if  (root == null ) {  return  result;  new  LinkedList <>();  boolean  isLeftToRight  =  true ; while  (!queue.isEmpty()) {  int  levelSize  =  queue.size();  new  LinkedList <>();  for  (int  i  =  0 ; i < levelSize; i++) {  TreeNode  node  =  queue.poll();  if  (isLeftToRight) {  else  {  if  (node.left != null ) {  if  (node.right != null ) {  new  ArrayList (levelList));  return  result;  
二叉树的层平均值 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class  Solution  {public  List<Double> averageOfLevels (TreeNode root)  {new  ArrayList <>();if  (root == null ) return  res;new  LinkedList <>();while  (list.size() != 0 ) {int  len  =  list.size();double  max  =  Double.MIN_VALUE;for  (int  i  =  0 ; i < len; i++) {TreeNode  node  =  list.poll();if  (node.left != null ) list.add(node.left);if  (node.right != null ) list.add(node.right);return  res;
力扣算法题打卡 Day 4 
2023年11月13日
 
合并两个有序数组 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class  Solution  {public  void  merge (int [] nums1, int  nums1_len, int [] nums2, int  nums2_len)  {int  i  =  nums1_len + nums2_len - 1 ;int  len1  =  nums1_len - 1 , len2 = nums2_len - 1 ;while  (len1 >= 0  && len2 >= 0 ) {if  (nums1[len1] <= nums2[len2])else  if  (nums1[len1] > nums2[len2])while  (len2 != -1 ) nums1[i--] = nums2[len2--];while  (len1 != -1 ) nums1[i--] = nums1[len1--];
反转字符串中的单词 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Solution  {public  String reverseWords (String s)  {if  (s == null  || s.length() == 0 ) {return  s;"\\s+" );return  String.join(" " , wordList);
验证回文串 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution  {public  boolean  isPalindrome (String s)  {StringBuffer  sgood  =  new  StringBuffer ();int  length  =  s.length();for  (int  i  =  0 ; i < length; i++) {char  ch  =  s.charAt(i);if  (Character.isLetterOrDigit(ch)) {StringBuffer  sgood_rev  =  new  StringBuffer (sgood).reverse();return  sgood.toString().equals(sgood_rev.toString());
删除指定元素 
1 2 3 4 5 6 7 8 9 10 11 12 13 class  Solution  {public  int  removeElement (int [] nums, int  val)  {int  slow  =  0 ;for  (int  fast  =  0 ; fast < nums.length; fast++) {if  (nums[fast] != val) {return  slow;
力扣算法题打卡 Day 5 
2023年11月14日
 
删除数组中的重复元素 
1 2 3 4 5 6 7 8 9 10 11 12 class  Solution  {public  int  removeDuplicates (int [] nums)  {int  slow  =  0 ;for (int  fast  =  1  ; fast<nums.length;fast++ ){if (nums[fast] != nums[slow]){return  slow + 1 ;
轮转数组 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class  Solution  {public  void  rotate (int [] nums, int  k)  {0 , nums.length - 1 );0 , k - 1 );1 );public  static  void  reverse (int [] nums, int  start, int  end)  {while  (start < end) {int  temp  =  nums[start];1 ;1 ;
分发糖果 
二叉树的最大深度 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  int  maxDepth (TreeNode root)  {if  (root == null ) {return  0 ;new  LinkedList <TreeNode>();int  ans  =  0 ;while  (!queue.isEmpty()) {int  size  =  queue.size();while  (size > 0 ) {TreeNode  node  =  queue.poll();if  (node.left != null ) {if  (node.right != null ) {return  ans;
力扣算法题打卡 Day 6 
2023年11月15日
 
判断两个二叉树是否相同 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class  Solution  {public  boolean  isSameTree (TreeNode p, TreeNode q)  {if  (p == null  && q == null ) {return  true ;else  if  (p == null  || q == null ) {return  false ;else  if  (p.val != q.val) {return  false ;else  {return  isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class  Solution  {public  boolean  isSameTree (TreeNode p, TreeNode q)  {if  (p == null  && q == null ) return  true ;  if  (p == null  || q == null ) return  false ;  if  (p.val != q.val) return  false ;  new  LinkedList <>();  while  (!queue.isEmpty()) {  TreeNode  node1  =  queue.poll();  TreeNode  node2  =  queue.poll();  if  (node1 != null  && node2 != null ) {  if  (node1.val != node2.val) return  false ;  else  if  (node1 != null  || node2 != null ) {  return  false ;  return  true ;  
存在重复元素Ⅱ 
1 2 3 4 5 6 7 8 9 10 11 12 class  Solution  {public  boolean  containsNearbyDuplicate (int [] nums, int  k)  {new  HashMap <>();  for  (int  i  =  0 ; i < nums.length; i++) {  if  (map.containsKey(nums[i]) && i - map.get(nums[i]) <= k) {  return  true ;  return  false ;  
汇总区间 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class  Solution  {public  List<String> summaryRanges (int [] nums)  {new  ArrayList <>();int  slow  =  0 ;for  (int  fast  =  0 ; fast < nums.length; fast++) {if  (fast + 1  == nums.length || nums[fast] + 1  != nums[fast + 1 ]) {StringBuilder  sb  =  new  StringBuilder ();if  (slow != fast) {"->" ).append(nums[fast]);1 ;return  res;
环形链表 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  class  Solution  {public  boolean  hasCycle (ListNode head)  {new  HashSet ();while (head != null ){if (!set.add(head)){return  true ;return  false ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public  class  Solution  {public  boolean  hasCycle (ListNode head)  {if  (head == null  || head.next == null ) {return  false ;ListNode  slow  =  head;ListNode  fast  =  head.next;while  (slow != fast) {if  (fast == null  || fast.next == null ) {return  false ;return  true ;
搜索插入位置 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class  Solution  {public  int  searchInsert (int [] nums, int  target)  {int  n  =  nums.length;int  left  =  0 , right = n - 1 , ans = n;while  (left <= right) {int  mid  =  ((right - left) >> 1 ) + left;if  (target <= nums[mid]) {1 ;else  {1 ;return  ans;
力扣算法题打卡 Day 7 
2023年11月16日
 
判断子序列 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution  {public  boolean  isSubsequence (String s, String t)  {int  sPointer  =  0 ; int  tPointer  =  0 ; while  (sPointer < s.length() && tPointer < t.length()) {if  (s.charAt(sPointer) == t.charAt(tPointer)) {return  sPointer == s.length(); 
最长公共前缀 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class  Solution  {public  String longestCommonPrefix (String[] strs)  {if  (strs == null  || strs.length == 0 ) {return  "" ;String  prefix  =  strs[0 ]; for  (int  i  =  1 ; i < strs.length; i++) {while  (strs[i].indexOf(prefix) != 0 ) {0 , prefix.length() - 1 );if  (prefix.isEmpty()) {return  "" ;return  prefix;
多数元素 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  Solution  {public  int  majorityElement (int [] nums)  {int  candidate  =  nums[0 ];  int  count  =  1 ;  for  (int  i  =  1 ; i < nums.length; i++) {if  (nums[i] == candidate) {else  {if  (count == 0 ) {1 ;  return  candidate;
罗马数字转整数 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class  Solution  {public  int  romanToInt (String s)  {int  result  =  0 ;new  HashMap <>();'I' , 1 );'V' , 5 );'X' , 10 );'L' , 50 );'C' , 100 );'D' , 500 );'M' , 1000 );for  (int  i  =  0 ; i < s.length(); i++) {if  (i < s.length() - 1  && map.get(s.charAt(i)) < map.get(s.charAt(i + 1 ))) {else  {return  result;
力扣算法题打卡 Day 8 
2023年11月17日
 
快乐数 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  boolean  isHappy (int  n)  {int  slow  =  n;int  fast  =  n;do  {while  (slow != fast);  return  slow == 1 ;  public  static  int  digitSquareSum (int  n)  {int  sum  =  0 ;while  (n > 0 ) {int  digit  =  n % 10 ;10 ;return  sum;
找出字符串中第一个匹配字符的下标 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class  Solution  {public  int  strStr (String haystack, String needle)  {int  n  =  haystack.length(), m = needle.length();for  (int  i  =  0 ; i + m <= n; i++) {boolean  flag  =  true ;for  (int  j  =  0 ; j < m; j++) {if  (haystack.charAt(i + j) != needle.charAt(j)) {false ;break ;if  (flag) {return  i;return  -1 ;
最后一个单词的长度 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class  Solution  {public  int  lengthOfLastWord (String s)  {String  s_trim  =  s.trim();" " );if  (words.length == 0 ) {return  0 ;return  words[words.length - 1 ].length();
买卖股票的最佳时机 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class  Solution  {public  int  maxProfit (int [] prices)  {int  minPrice  =  Integer.MAX_VALUE;int  maxProfit  =  0 ;for  (int  price : prices) {if  (price < minPrice) {else  {int  profit  =  price - minPrice;return  maxProfit;
力扣算法题打卡 Day 9 
2023年11月18日
 
力扣算法题打卡 Day 10 
2023年11月19日
 
赎金信 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class  Solution  {public  boolean  canConstruct (String ransomNote, String magazine)  {new  HashMap <>();  for  (char  c : magazine.toCharArray()) {  0 ) + 1 );  for  (char  c : ransomNote.toCharArray()) {  int  count  =  charCount.getOrDefault(c, 0 );  if  (count == 0 ) {  return  false ;  else  {  1 );  return  true ;  
同构字符串 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class  Solution  {public  boolean  isIsomorphic (String s, String t)  {if  (s.length() != t.length()) {  return  false ;  new  HashMap <>();   for  (int  i  =  0 ; i < s.length(); i++) {  char  c1  =  s.charAt(i);  char  c2  =  t.charAt(i);  if  (map.containsKey(c1)) { if  (map.get(c1) != c2) {  return  false ;  else  { if  (map.containsValue(c2)) {  return  false ;  return  true ;  
单词规律 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class  Solution  {public  boolean  wordPattern (String pattern, String s)  {" " );if  (words.length != pattern.length()) {return  false ;new  HashMap <>();for  (int  i  =  0 ; i < pattern.length(); i++) {char  c  =  pattern.charAt(i);if  (map.containsKey(c)) {if  (!map.get(c).equals(words[i])) {return  false ;else  {if  (map.containsValue(words[i])) {return  false ;return  true ;
有效字母异位词 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class  Solution  {public  boolean  isAnagram (String s, String t)  {if  (s.length() != t.length()) {return  false ;int [] counter = new  int [26 ];  for  (int  i  =  0 ; i < s.length(); i++) {'a' ]++;'a' ]--;for  (int  count : counter) {if  (count != 0 ) {return  false ;return  true ;
力扣算法题打卡 Day 11 
2023年11月20日
 
二进制求和 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class  Solution  {public  String addBinary (String a, String b)  {StringBuilder  result  =  new  StringBuilder ();int  ca  =  0 ;for  (int  i  =  a.length() - 1 , j = b.length() - 1 ; i >= 0  || j >= 0  || ca == 1 ; i--, j--) {int  sum  =  ca;if  (i >= 0 ) sum += a.charAt(i) - '0' ;if  (j >= 0 ) sum += b.charAt(j) - '0' ;2 );2 ;return  result.reverse().toString();
回文数 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution  {public  boolean  isPalindrome (int  x)  {if  (x < 0 ) {return  false ;int  reversed  =  0 ;int  original  =  x;while  (x != 0 ) {int  digit  =  x % 10 ;10  + digit;10 ;return  original == reversed;
爬楼梯 
1 2 3 4 5 6 7 8 9 10 class  Solution  {public  int  climbStairs (int  n)  {if  (n <= 2 ) {  return  n;  return  climbStairs(n - 1 ) + climbStairs(n - 2 );  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class  Solution  {public  int  climbStairs (int  n)  {if  (n <= 2 ) {  return  n;  int [] dp = new  int [n + 1 ];  1 ] = 1 ;  2 ] = 2 ;  for  (int  i  =  3 ; i <= n; i++) {  1 ] + dp[i - 2 ];  return  dp[n];  
路径总和 
1 2 3 4 5 6 7 8 9 10 11 12 13 class  Solution  {public  boolean  hasPathSum (TreeNode root, int  targetSum)  {if  (root == null ) {return  false ;if  (root.left == null  && root.right == null ) {return  targetSum == root.val;return  hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class  Solution  {public  boolean  hasPathSum (TreeNode root, int  targetSum)  {if  (root == null ) {return  false ;new  LinkedList <TreeNode>();new  LinkedList <Integer>();while  (!queNode.isEmpty()) {TreeNode  now  =  queNode.poll();int  temp  =  queVal.poll();if  (now.left == null  && now.right == null ) {if  (temp == targetSum) {return  true ;continue ;if  (now.left != null ) {if  (now.right != null ) {return  false ;
完全二叉树的节点个数 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  int  countNodes (TreeNode root)  {if  (root == null ) {return  0 ;int  leftDepth  =  getDepth(root.left);int  rightDepth  =  getDepth(root.right);if  (leftDepth == rightDepth) {return  (int ) Math.pow(2 , leftDepth) + countNodes(root.right);else  {return  (int ) Math.pow(2 , rightDepth) + countNodes(root.left);public  int  getDepth (TreeNode node)  {int  depth  =  0 ;while  (node != null ) {return  depth;
力扣算法题打卡 Day 12 
2023年11月21日
 
数组加一 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class  Solution  {public  int [] plusOne(int [] digits) {for  (int  i  =  digits.length - 1 ; i >= 0 ; i--) {if  (digits[i] < 9 ) {return  digits;0 ;int [] newDigits = new  int [digits.length + 1 ];0 ] = 1 ;return  newDigits;
X 的平方根 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  Solution  {public  int  mySqrt (int  x)  {if  (x == 0 ) {return  0 ;int  left  =  1 ;int  right  =  x;while  (left <= right) {int  mid  =  left + (right - left) / 2 ;if  (mid == x / mid) {return  mid;else  if  (mid < x / mid) {1 ;else  {1 ;return  right;
只出现一次的数字 
1 2 3 4 5 6 7 8 9 10 class  Solution  {public  int  singleNumber (int [] nums)  {int  result  =  0 ;for  (int  num : nums) {return  result;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution  {public  int  singleNumber (int [] nums)  {new  HashSet <>();for  (int  num : nums) {if  (set.contains(num)) {else  {return  set.iterator().next();
位1的个数 
1 2 3 4 5 6 7 8 9 10 11 public  class  Solution  {public  int  hammingWeight (int  n)  {int  count  =  0 ;while  (n != 0 ) {1 );return  count;
颠倒二进制位 
1 2 3 4 5 6 7 8 9 10 11 public  class  Solution  {public  int  reverseBits (int  n)  {int  result  =  0 ;for  (int  i  =  0 ; i < 32 ; i++) {1 ) | (n & 1 );1 ;return  result;
力扣算法题打卡 Day 13 
2023年11月22日
 
未打卡 力扣算法题打卡 Day 14 
2023年11月23日
 
买卖股票的最佳时机(可多次购买) 
跳跃游戏 
最长连续序列 
力扣算法题打卡 Day 15 
2023年11月24日
 
未打卡 力扣算法题打卡 Day 16 
2023年11月25日
 
两数之和(有序数组) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class  Solution  {public  int [] twoSum(int [] numbers, int  target) {new  HashMap <>();for  (int  i  =  0 ; i < numbers.length; i++) {int  complement  =  target - numbers[i];if  (map.containsKey(complement)) {return  new  int []{map.get(complement) + 1 , i + 1 };return  new  int [0 ];
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class  Solution  {public  int [] twoSum(int [] numbers, int  target) {int  left  =  0 ;int  right  =  numbers.length - 1 ;while  (left < right) {int  sum  =  numbers[left] + numbers[right];if  (sum == target) {return  new  int []{left + 1 , right + 1 };else  if  (sum < target) {else  {return  new  int []{-1 , -1 }; 
盛水最多的容器 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class  Solution  {public  int  maxArea (int [] height)  {int  left  =  0 ;int  right  =  height.length - 1 ;int  maxArea  =  0 ;while  (left < right) {int  minHeight  =  Math.min(height[left], height[right]);int  area  =  minHeight * (right - left);if  (height[left] < height[right]) {else  {return  maxArea;
三数之和 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class  Solution  {public  List<List<Integer>> threeSum (int [] nums)  {new  ArrayList <>();if  (nums == null  || nums.length < 3 ) {return  result;for  (int  i  =  0 ; i < nums.length - 2 ; i++) {if  (i > 0  && nums[i] == nums[i - 1 ]) {continue ;int  left  =  i + 1 ;int  right  =  nums.length - 1 ;while  (left < right) {int  sum  =  nums[i] + nums[left] + nums[right];if  (sum == 0 ) {while  (left < right && nums[left] == nums[left + 1 ]) {while  (left < right && nums[right] == nums[right - 1 ]) {else  if  (sum < 0 ) {else  {return  result;
分隔链表 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class  Solution  {public  ListNode partition (ListNode head, int  x)  {if  (head == null  || head.next == null ) {return  head;ListNode  lessHead  =  new  ListNode (0 );ListNode  moreHead  =  new  ListNode (0 );ListNode  less  =  lessHead;ListNode  more  =  moreHead;while  (head != null ) {if  (head.val < x) {else  {null ;return  lessHead.next;
力扣算法题打卡 Day 17 
2023年11月26日
 
合并区间 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class  Solution  {public  int [][] merge(int [][] intervals) {if  (intervals.length <= 1 ) {return  intervals;0 ] - v2[0 ]);int [][] res = new  int [intervals.length][2 ];int  idx  =  -1 ;for  (int [] interval : intervals) {if  (idx == -1  || interval[0 ] > res[idx][1 ]) {else  {1 ] = Math.max(res[idx][1 ], interval[1 ]);return  Arrays.copyOf(res, idx + 1 );
字母异位词分组 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  Solution  {public  List<List<String>> groupAnagrams (String[] strs)  {if  (strs.length == 0 ) return  new  ArrayList <>();new  HashMap <>();for  (String s : strs) {char [] ca = s.toCharArray();String  keyStr  =  String.valueOf(ca);if  (!map.containsKey(keyStr)) new  ArrayList <>());return  new  ArrayList <>(map.values());
长度最小的子数组 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class  Solution  {public  int  minSubArrayLen (int  target, int [] nums)  {int  n  =  nums.length;int  ans  =  Integer.MAX_VALUE;int  sum  =  0 ;int  start  =  0 ;for  (int  end  =  0 ; end < n; end++) {while  (sum >= target) {1 );return  ans == Integer.MAX_VALUE ? 0  : ans;
力扣算法题打卡 Day 18 
2023年11月27日
 
力扣算法题打卡 Day 19 
2023年11月28日
 
力扣算法题打卡 Day 20 
2023年11月29日
 
插入区间 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class  Solution  {public  int [][] insert(int [][] intervals, int [] newInterval) {int [][] res = new  int [intervals.length + 1 ][2 ];int  idx  =  0 ;int  i  =  0 ;while  (i < intervals.length && intervals[i][1 ] < newInterval[0 ]) {while  (i < intervals.length && intervals[i][0 ] <= newInterval[1 ]) {0 ] = Math.min(intervals[i][0 ], newInterval[0 ]);1 ] = Math.max(intervals[i][1 ], newInterval[1 ]);while  (i < intervals.length) {return  Arrays.copyOf(res, idx);
🍖 注意:
 
不确保新插入的区间是否能与原区间合并,所以新的区间容量保守加一: 
 
1 int [][] res = new  int [intervals.length + 1 ][2 ];
区间插入成功后,如果未发生合并,直接返回 res 数组是没问题的。 
但如果发生了合并,则新数组的容量是多一位的,直接返回 res 就会出问题: 
 
而新数组的真实容量大小是由 idx 决定的,直接限制返回数组的容量:(2023/01/12早)  
 
1 return  Arrays.copyOf(res, idx);
用最少的箭引爆气球 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  Solution  {public  int  findMinArrowShots (int [][] points)  {if  (points == null  || points.length == 0 ) {return  0 ;0 ] - b[0 ]);int  arrows  =  1 ;int  end  =  points[0 ][1 ];for  (int  i  =  1 ; i < points.length; i++) {if  (points[i][0 ] > end) {1 ];return  arrows;
简化路径 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class  Solution  {public  String simplifyPath (String path)  {new  Stack <>();"/" );for  (String part : parts) {if  (part.equals(".." )) {if  (!stack.isEmpty()) {else  if  (!part.isEmpty() && !part.equals("." )) {StringBuilder  result  =  new  StringBuilder ();for  (String dir : stack) {"/" ).append(dir);return  result.length() > 0  ? result.toString() : "/" ;
LRU 缓存 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  LRUCache  extends  LinkedHashMap <Integer, Integer>{private  int  capacity;public  LRUCache (int  capacity)  {super (capacity, 0.75F , true );this .capacity = capacity;public  int  get (int  key)  {return  super .getOrDefault(key, -1 );public  void  put (int  key, int  value)  {super .put(key, value);@Override protected  boolean  removeEldestEntry (Map.Entry<Integer, Integer> eldest)  {return  size() > capacity; 
力扣算法打卡 Day 21 
2023年12月6日
 
无重复字符的最长字串 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class  Solution  {public  int  lengthOfLongestSubstring (String s)  {if  (s.length()==0 ) return  0 ;new  HashMap <Character, Integer>();int  max  =  0 ;int  left  =  0 ;for (int  i  =  0 ; i < s.length(); i ++){char  c  =  s.charAt(i);if (map.containsKey(c)){1 );1 );return  max;
逆波兰表达式求值 
2023年12月5号
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class  Solution  {public  int  evalRPN (String[] tokens)  {new  LinkedList <Integer>();int  n  =  tokens.length;for  (int  i  =  0 ; i < n; i++) {String  token  =  tokens[i];if  (isNumber(token)) {else  {int  num2  =  stack.pop();int  num1  =  stack.pop();switch  (token) {case  "+" :break ;case  "-" :break ;case  "*" :break ;case  "/" :break ;default :return  stack.pop();public  boolean  isNumber (String token)  {return  !("+" .equals(token) || "-" .equals(token) || "*" .equals(token) || "/" .equals(token));
力扣算法打卡 Day 22 
2023年12月8日
 
除自身以外数组的乘积 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class  Solution  {public  int [] productExceptSelf(int [] nums) {int  n  =  nums.length;  int [] answer = new  int [n];  int [] left = new  int [n];  int [] right = new  int [n];  0 ] = 1 ;  for  (int  i  =  1 ; i < n; i++) {  1 ] * nums[i-1 ];  1 ] = 1 ;  for  (int  i  =  n-2 ; i >= 0 ; i--) {  1 ] * nums[i+1 ];  for  (int  i  =  0 ; i < n; i++) {  return  answer;  
加油站 
2023年12月5号
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class  Solution  {public  int  canCompleteCircuit (int [] gas, int [] cost)  {int  totalGas  =  0 ;  int  currentGas  =  0 ;  int  startStation  =  0 ;  for  (int  i  =  0 ; i < gas.length; i++) {  if  (currentGas < 0 ) {  1 ;  0 ;  if  (totalGas < 0 ) {  return  -1 ;  return  startStation;  
力扣算法打卡 Day 23 
2024年1月6日
 
冒泡排序 
1 2 3 4 5 6 7 8 public  static  void  main (String[] args)  {int [] arr = {64 , 34 , 25 , 12 , 22 , 11 , 90 };"排序后的数组:" );for  (int  i : arr) {" " );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public  static  void  bubbleSort2 (int [] arr)  {int  length  =  arr.length;for  (int  i  =  0 ; i < length - 1 ; i++) {for  (int  j  =  0 ; j < length - 1  - i; j++) {if  (arr[j] > arr[j + 1 ])1 ));public  static  void  swap (int [] arr, int  i, int  j)  {int  temp  =  arr[i];
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public  static  void  bubbleSort3 (int [] arr)  {int  length  =  arr.length;for  (int  i  =  0 ; i < length - 1 ; i++) {boolean  swap  =  false ;for  (int  j  =  0 ; j < length - 1  - i; j++) {if  (arr[j] > arr[j + 1 ]) {1 ));true ;"Round "  + (i + 1 ) + ": "  + Arrays.toString(arr));if  (!swap) {"数组已经有序,直接结束" );break ;public  static  void  swap (int [] arr, int  i, int  j)  {int  temp  =  arr[i];
深入理解冒泡排序:比较次数、交换次数、是否发生比较 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public  static  void  bubbleSort4 (int [] arr)  {int  length  =  arr.length;for  (int  i  =  0 ; i < length - 1 ; i++) {int  compareNum  =  0 ;int  swapNum  =  0 ;boolean  isSwap  =  false ;for  (int  j  =  0 ; j < length - 1  - i; j++) {if  (arr[j] > arr[j + 1 ]) {1 ));true ;"Round "  + (i + 1 ) + ": "  + Arrays.toString(arr));"本轮共比较"  + compareNum + "次" );"本轮共交换"  + swapNum + "次" );if  (!isSwap) {"数组已经有序,直接结束" );break ;
选择排序 
1 2 3 4 5 6 7 8 public  static  void  main (String[] args)  {int [] arr = {64 , 34 , 25 , 12 , 22 , 11 , 90 };"排序后的数组:" );for  (int  i : arr) {" " );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public  static  void  selectionSort2 (int [] arr)  {int  length  =  arr.length;for  (int  i  =  0 ; i < length; i++) {int  index  =  i;for  (int  j  =  i + 1 ; j < length; j++) {if  (arr[j] < arr[index]) {public  static  void  swap (int [] arr, int  i, int  j)  {int  temp  =  arr[i];
优化点:发生选举后作交换、使用位运算交换、不使用临时变量作交换 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  static  void  selectionSort2 (int [] arr)  {int  length  =  arr.length;for  (int  i  =  0 ; i < length; i++) {int  index  =  i;for  (int  j  =  i + 1 ; j < length; j++) {if  (arr[j] < arr[index]) {if  (i != index) {
1 2 3 4 5 6 7 8 9 10 11 public  static  void  swap2 (int [] arr, int  i, int  j)  {public  static  void  swap3 (int [] arr, int  i, int  j)  {
踩了个大坑,未发生过选举就作交换,即元素与本身作交换,使用后两种交换方法会出问题: 
 
想一想这是为什么,跟引用有关系(2024/01/06早)  
 
插入排序 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public  static  void  insertionSort2 (int [] arr)  {int  length  =  arr.length;for  (int  i  =  1 ; i < length; i++) {int  key  =  arr[i];int  j  =  i - 1 ;while  (j >= 0  && arr[j] > key) {1 ] = arr[j];1 ] = key;
优化点:把查找过程改造为二分查找,减少比较次数,这里按下不表 
 
快速排序 一般方法 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public  static  void  quickSort2 (int [] arr, int  low, int  high)  {if  (low < high) {int  key  =  arr[high];int  i  =  low - 1 ;for  (int  j  =  low; j < high; j++) {if  (arr[j] < key) {int  index  =  i + 1 ;1 );1 , high);
在语雀画板上画个图就能明白,理解:使用 i 维护分界点;每轮快排之后基准值位置的确定 
 
快慢指针法 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public  static  void  quickSort4 (int [] arr, int  low, int  high)  {if  (low >= high) {return ;int  point  =  arr[low];int  slow  =  low;int  fast  =  low + 1 ;while  (fast <= high) {if  (arr[fast] < point) {int  temp  =  arr[slow];int  temp  =  arr[slow];1 );1 , high);
重点在于理解:选取基准值为靠左,快指针检索,慢指针维护分界 
 
堆排序 力扣算法打卡 Day 23 
2024年1月15日
 
打家劫舍 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public  class  Solution  {  public  int  rob (int [] nums)  {  if  (nums == null  || nums.length == 0 ) {  return  0 ;  if  (nums.length == 1 ) {  return  nums[0 ];  if  (nums.length == 2 ) {  return  Math.max(nums[0 ], nums[1 ]);  int [] dp = new  int [nums.length];  0 ] = nums[0 ];  1 ] = Math.max(nums[0 ], nums[1 ]);for  (int  i  =  2 ; i < nums.length; i++) {  2 ] + nums[i], dp[i-1 ]);  return  dp[nums.length - 1 ];  
力扣算法打卡 Day 24 
2024年1月16日
 
划分字母区间 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public  static  List<Integer> partitionLabels (String s)  {int [] last = new  int [26 ];int  length  =  s.length();for  (int  i  =  0 ; i < length; i++) {'a' ] = i;new  ArrayList <>();int  start  =  0 , end = 0 ;for  (int  i  =  0 ; i < length; i++) {'a' ]);if  (i == end) {1 );1 ;return  partition;
子数组最大平均数 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public  static  double  findMaxAverage (int [] nums, int  k)  {int  len  =  nums.length;int  windowSum  =  0 ;if  (k > len || len < 1  || k < 1 ) {return  0 ;for  (int  i  =  0 ; i < k; i++) {int  res  =  windowSum;for  (int  right  =  k; right < len; right++) {return  (double ) res / k;
最长连续递增序列 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  int  findLengthOfLCIS (int [] nums)  {int  left  =  0 ;int  right  =  0 ;int  res  =  0 ;while  (right < nums.length) {if  (right > 0  && nums[right - 1 ] >= nums[right]) {return  res;
最长连续序列 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  int  longestConsecutive (int [] nums)  {new  HashSet <>();for  (int  num : nums) {int  longestStreak  =  0 ;for  (int  num : set) {if  (!set.contains(num - 1 )) {int  currentNum  =  num;int  currentStreak  =  1 ;while  (set.contains(currentNum + 1 )) {1 ;1 ;return  longestStreak;
力扣算法打卡 Day 25 
2024年1月17日
 
长度最小的子数组 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class  Solution  {public  int  minSubArrayLen (int  target, int [] nums)  {int  left  =  0 ;int  right  =  0 ;int  sum  =  0 ;int  min  =  Integer.MAX_VALUE;while (right < nums.length){while (sum>= target){1 );return  min == Integer.MAX_VALUE ? 0  : min;
其中,核心代码可以改写为:
1 2 3 4 5 6 7 while (right < nums.length){while (sum>= target){
算法佛脚 120 题 链表 栈、队列和 Hash 1、栈实现 
实现一个简单的栈,支持入栈、出栈、弹出栈顶元素、判空操作  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 class  Mystack <T> {    null ;int  top;public  Mystack ()  {this .stack = new  Object [10 ];this .top = 0 ;public  void  push (T t)  {1 );this .stack[top] = t;public  T peek ()  {T  t  =  null ;if  (!isEmpty()) {this .stack[top - 1 ];return  t;public  T pop ()  {T  t  =  this .peek();if  (!isEmpty()) {this .stack[top - 1 ] = null ;return  t;public  Boolean isEmpty ()  {return  top == 0 ;public  int  getSize ()  {return  stack.length;public  void  expandCapacity (int  size)  {if  (size > getSize()) {1 ;this .stack, size);public  static  void  main (String[] args)  {new  Mystack <>();"java" );"is" );"beautiful" );"language" );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 public  class  ListStack <T> {public  int  size;static  class  Node <T> {public  T t;public  Node next;public  Node (T t)  {this .t = t;this .next = null ;public  Node head;public  ListStack ()  {null ;public  void  push (T t)  {if  (!isEmpty()) {new  Node <>(t);else  {new  Node (t);this .size++;public  T peek ()  {T  t  =  null ;if  (!isEmpty()) {return  t;public  T pop ()  {T  t  =  null ;if  (!isEmpty()) {this .size--;return  t;public  Boolean isEmpty ()  {return  head == null ;public  int  getSize ()  {return  this .size;public  static  void  main (String[] args)  {new  ListStack <>();"java" );"is" );"beautiful" );"language" );
2、队列实现 
实现一个简单的队列,支持入队、出队、遍历队列、判空操作
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public  class  LinkQueue  {private  Node front;private  Node rear;private  int  size;public  LinkQueue ()  {this .front = new  Node (0 );this .rear = new  Node (0 );public  void  push (int  value)  {Node  newNode  =  new  Node (value);Node  temp  =  front;while  (temp.next != null ) {public  int  pull ()  {if  (front.next == null ) {"队列已空" );Node  firstNode  =  front.next;return  firstNode.data;public  void  traverse ()  {Node  temp  =  front.next;while  (temp != null ) {"\t" );static  class  Node  {public  int  data;public  Node next;public  Node (int  data)  {this .data = data;public  static  void  main (String[] args)  {LinkQueue  linkQueue  =  new  LinkQueue ();1 );2 );3 );"第一个出队的元素为:"  + linkQueue.pull());"队列中的元素为:" );
3、括号匹配问题 
LeetCode20. 给定⼀个只包括 ‘(‘,’)’,’{‘,’}’,’[‘,’]’ 的字符串 s ,判断字符串是否有效。
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 static  boolean  isValid (String s)  {if  (s.length() <= 1 ) {return  false ;new  HashMap <>();'(' , ')' );'{' , '}' );'[' , ']' );new  Stack <>();for  (int  i  =  0 ; i < s.length(); i++) {char  item  =  s.charAt(i);if  (smap.containsKey(item)) {else  {if  (stack.isEmpty()) {return  false ;Character  left  =  stack.pop();char  rightChar  =  smap.get(left);if  (rightChar != item) {return  false ;return  stack.isEmpty();
2.LeetCode 155,设计⼀个⽀持 push ,pop ,top 操作,并能在常数时间内检索到最⼩元素的栈。
3.LeetCode 716.设计⼀个最⼤栈数据结构,既⽀持栈操作,⼜⽀持查找栈中最⼤元素。
4.LeetCode227.给你⼀个字符串表达式 s ,请你实现⼀个基本计算器来计算并返回它的值。
5.LeetCode150.根据 逆波兰表示法,求表达式的值
6.LeetCode232 请你仅使⽤两个栈实现先⼊先出队列。队列应当⽀持⼀般队列⽀持的所有操作(push、pop、
peek、empty)
7.leetcode225 请你仅使⽤两个队列实现⼀个后⼊先出(LIFO)的栈,并⽀持普通栈的全部四种操作(push、
top、pop 和 empty)。
8.LeetCode1.给定⼀个整数数组 nums 和⼀个整数⽬标值 target,请你在该数组中找出 和为⽬标值 target 的那两
个整数,并返回它们的数组下标。
9.LeetCode146:运⽤你所掌握的数据结构,设计和实现⼀个LRU (最近最少使⽤) 缓存机制
10.LeetCode460:运⽤你所掌握的数据结构,设计和实现⼀个LFU 缓存机制
蓝桥杯热门赛题 终极算法笔记 手把手刷链表算法
双指针:合并链表、分割链表、合并K个有序链表、单链表中点、单链表倒数第K个节点、判断链表是否包含环、判断链表相交 
链表反转:反转链表、反转前n个节点、反转区间、K个一组反转链表 
判断回文链表:压栈,反转,双指针 
 
简单的链表算法 合并链表 解法思路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ListNode mergeTwoLists (ListNode l1, ListNode l2)  {ListNode  dummy  =  new  ListNode (-1 );ListNode  p1  =  l1, p2 = l2;ListNode  p  =  dummy;while  (p1 != null  && p2 != null ) {if  (p1.val > p2.val) {else  {null  ? p2 : p1;return  dummy.next;
分割链表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ListNode partition (ListNode head, int  x)  {ListNode  dummy1  =  new  ListNode (-1 );ListNode  dummy2  =  new  ListNode (-1 );ListNode  p1  =  dummy1, p2 = dummy2;ListNode  p  =  head;while  (p != null ) {if  (p.val >= x) {else  {ListNode  temp  =  p.next;null ;return  dummy1.next;
合并K个有序链表 简单实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class  Solution  {public  ListNode mergeKLists (ListNode[] lists)  {ListNode  res  =  null ;for  (ListNode list : lists) {return  res;public  static  ListNode mergeTwoListsMoreSimple (ListNode l1, ListNode l2)  {ListNode  prehead  =  new  ListNode (-1 );ListNode  prev  =  prehead;while  (l1 != null  && l2 != null ) {if  (l1.val <= l2.val) {else  {null  ? l2 : l1;return  prehead.next;
基于优先级队列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ListNode mergeKLists (ListNode[] lists)  {if  (lists.length == 0 ) return  null ;ListNode  dummy  =  new  ListNode (-1 );ListNode  p  =  dummy;new  PriorityQueue <>(for  (ListNode head : lists) {if  (head != null )while  (!pq.isEmpty()) {ListNode  node  =  pq.poll();if  (node.next != null ) {return  dummy.next;
寻找倒数第 K 个节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public  ListNode FindKthToTail  (ListNode pHead, int  k)  {if  (pHead == null  || k <= 0 ) {return  null ;ListNode  fast  =  pHead;ListNode  slow  =  pHead;for  (int  i  =  0 ; i < k; i++) {if  (fast == null ) {return  null ;while  (fast != null ) {return  slow;
删除倒数第K个节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public  ListNode removeNthFromEnd (ListNode head, int  n)  {ListNode  dummy  =  new  ListNode (-1 );ListNode  x  =  findFromEnd(dummy, n + 1 );return  dummy.next;private  ListNode findFromEnd (ListNode head, int  k)  {findFromEnd (ListNode head, int  k)  {ListNode  p1  =  head;for  (int  i  =  0 ; i < k; i++) {ListNode  p2  =  head;while  (p1 != null ) {return  p2;
单链表中点 1 2 3 4 5 6 7 8 9 10 11 12 ListNode middleNode (ListNode head)  {ListNode  slow  =  head, fast = head;while  (fast != null  && fast.next != null ) {return  slow;
判断链表是否包含环 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 boolean  hasCycle (ListNode head)  {ListNode  slow  =  head, fast = head;while  (fast != null  && fast.next != null ) {if  (slow == fast) {return  true ;return  false ;
链表寻找环起点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  ListNode detectCycle (ListNode head)  {while  (fast != null  && fast.next != null ) {if  (fast == slow) break ;if  (fast == null  || fast.next == null ) {return  null ;while  (slow != fast) {return  slow;
判断链表相交 1 2 3 4 5 6 7 8 9 10 11 12 13 ListNode getIntersectionNode (ListNode headA, ListNode headB)  {ListNode  p1  =  headA, p2 = headB;while  (p1 != p2) {if  (p1 == null ) p1 = headB;else             p1 = p1.next;if  (p2 == null ) p2 = headA;else             p2 = p2.next;return  p1;
链表反转 链表反转 递归反转整个链表:
1 2 3 4 5 6 7 8 9 10 reverse (ListNode head)  {if  (head == null  || head.next == null ) {return  head;ListNode  last  =  reverse(head.next);null ;return  last;
迭代反转整个链表:
1 2 3 4 5 6 7 8 9 10 11 public  ListNode reverseList (ListNode head)  {ListNode  ans  =  new  ListNode (-1 );ListNode  cur  =  head;while  (cur != null ) {ListNode  next  =  cur.next;return  ans.next;
1 2 3 4 5 6 7 8 9 10 11 public  ListNode reverseList (ListNode head)  {ListNode  prev  =  null ;ListNode  curr  =  head;while  (curr != null ) {ListNode  next  =  curr.next;return  prev;
反转前 N 个节点 递归反转前 N 个节点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ListNode  successor  =  null ; reverseN (ListNode head, int  n)  {if  (n == 1 ) {return  head;ListNode  last  =  reverseN(head.next, n - 1 );return  last;
区间反转 递归反转一个区间:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ListNode reverseBetween (ListNode head, int  m, int  n)  {if  (m == 1 ) {return  reverseN(head, n);1 , n - 1 );return  head;ListNode  successor  =  null ; reverseN (ListNode head, int  n)  {if  (n == 1 ) {return  head;ListNode  last  =  reverseN(head.next, n - 1 );return  last;
迭代反转一个区间,穿针引线法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Solution  {public  ListNode reverseBetween (ListNode head, int  left, int  right)  {ListNode  dummyNode  =  new  ListNode (-1 );ListNode  pre  =  dummyNode;for  (int  i  =  0 ; i < left - 1 ; i++) {ListNode  cur  =  pre.next;for  (int  i  =  0 ; i < right - left; i++) {return  dummyNode.next;
迭代反转一个区间,头插法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class  Solution  {public  ListNode reverseBetween (ListNode head, int  left, int  right)  {ListNode  dummyNode  =  new  ListNode (-1 );ListNode  pre  =  dummyNode;for  (int  i  =  0 ; i < left - 1 ; i++) {ListNode  rightNode  =  pre;for  (int  i  =  0 ; i < right - left + 1 ; i++) {ListNode  leftNode  =  pre.next;null ;ListNode  post  =  rightNode.next;null ;return  dummyNode.next;public  static  ListNode reverseList (ListNode head)  {ListNode  ans  =  new  ListNode (-1 );ListNode  cur  =  head;while  (cur != null ) {ListNode  next  =  cur.next;return  ans.next;
K 个一组反转链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class  Solution  {public  ListNode reverse (ListNode a, ListNode b)  {ListNode  dummy  =  new  ListNode (-1 );while (a != b){ListNode  next  =  a.next;return  dummy.next;public  ListNode reverseKGroup (ListNode head, int  k)  {if (head == null ) return  null ;for  (int  i  =  0 ; i < k; i++){if  (b == null ) return  head;ListNode  newHead  =  reverse(a, b);return  newHead;
判断回文链表 判断回文链表:压栈,反转,双指针
压栈 压栈法判断回文链表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public  static  boolean  isPalindromeByAllStack (ListNode head)  {ListNode  temp  =  head;new  Stack <>();while  (temp != null ) {while  (head != null ) {if  (head.val != stack.pop()) {return  false ;return  true ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public  static  boolean  isPalindromeByHalfStack (ListNode head)  {if  (head == null )return  true ;ListNode  temp  =  head;new  Stack <>();int  len  =  0 ;while  (temp != null ) {1 ;while  (len-- >= 0 ) {if  (head.val != stack.pop())return  false ;return  true ;
反转 反转链表思路很简单,使用任意一种方法反转链表,同时遍历反转后的链表和原链表,即可判断原链表是否为回文链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class  Solution  {  public  static  boolean  isPalindrome (ListNode head)  {ListNode  ans  =  new  ListNode (-1 );ListNode  cur  =  head;while  (cur != null ) {ListNode  next  =  cur.next;ListNode  newHead  =  ans.next;while  (newHead != null  && head != null ) {if  (head.val != newHead.val)return  false ;return  true ;
正常思路一定是像上面这样,但结果是错误的,因为这样会将原链表反转,而我们需要构造新的反转链表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class  Solution  {  public  static  boolean  isPalindrome (ListNode head)  {ListNode  ans  =  new  ListNode (-1 );ListNode  temp  =  head;while  (temp != null ) {ListNode  cur  =  new  ListNode (temp.val); ListNode  newHead  =  ans.next;while  (newHead != null  && head != null ) {if  (head.val != newHead.val)return  false ;return  true ;
双指针 双指针判断回文字符串:
1 2 3 4 5 6 7 8 9 10 11 12 boolean isPalindrome(String s )  {int  left = 0 , right = s.length()  - 1 ;while  (left < right) {if  (s.char At(left )  != s.char At(right ) ) {false ;true ;
双指针寻找回文字符串:
1 2 3 4 5 6 7 8 9 10 11 String palindrome(String s, int  left , int  right ) {left  >= 0  && right  < s.length()left ) == s.charAt(right )) {left --;right ++;left ] 和 s[right ] 为中心的最长回文串left  + 1 , right );
递归 + 反转实现类双指针判断回文链表:(2024/01/30晚) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 boolean  isPalindrome (ListNode head)  {while  (fast != null  && fast.next != null ) {if  (fast != null )ListNode  left  =  head;ListNode  right  =  reverse(slow);while  (right != null ) {if  (left.val != right.val)return  false ;return  true ;reverse (ListNode head)  {ListNode  pre  =  null , cur = head;while  (cur != null ) {ListNode  next  =  cur.next;return  pre;
牛客 TOP 100 
2024年2月27日
 
链表反转 :
迭代:定义虚拟节点;从节点1开始,根据虚拟节点后继,设置每个节点后继;更新虚拟节点后继;节点向后移动,提前更新节点后继。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public  class  Solution  {public  ListNode ReverseList  (ListNode head)  {ListNode  ans  =  new  ListNode (0 );ListNode  cur  =  head;while (cur != null ){ListNode  next  =  cur.next;return  ans.next;
递归:校验节点是否为空;设置终止条件,递归到最后一个节点停止;开始回溯,设置节点后继;断掉新后继节点的原先后继;向外抛回新的头节点。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public  ListNode ReverseList  (ListNode head)  {if (head == null ){return  head;if (head.next == null ){return  head;ListNode  last  =  ReverseList(head.next);null ;return  last;
区间反转 :
迭代(头插法):定义虚拟节点;迭代,单独拿到左右区间节点,断开与整体联系;链表反转,反转区间;反转完成,拼接链表 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50     public  ListNode reverseBetween  (ListNode head, int  m, int  n)  {ListNode  dummy  =  new  ListNode (0 );ListNode  pre  =  dummy;for (int  i  =  0 ; i < m - 1 ; i++){ListNode  rightNode  =  pre;for (int  i  =  0 ; i < n - m + 1 ; i++){ListNode  leftNode  =  pre.next;null ;ListNode  post  =  rightNode.next;null ;return  dummy.next;public  static  ListNode reverseList (ListNode head)  {ListNode  ans  =  new  ListNode (-1 );ListNode  cur  =  head;while  (cur != null ) {ListNode  next  =  cur.next;return  ans.next;
合并链表 :定义虚拟头节点;两链表均不为空,着手合并;两链表从头比较,优先合并小节点,否则合并大节点;节点向后移动;一条链表合并完毕,直接拼接剩下的链表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public  ListNode Merge  (ListNode pHead1, ListNode pHead2)  {ListNode  dummy  =  new  ListNode (-1 );ListNode  p1  =  pHead1, p2 = pHead2;ListNode  p  =  dummy;while (p1 != null  && p2 != null ) {if  (p1.val > p2.val) {else  {null  ? p2 : p1; return  dummy.next;
合并 K 个已排序的链表 :从头开始,遍历所有链表头节点,做到两两合并。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public  ListNode mergeKLists  (ArrayList<ListNode> lists)  {ListNode  res  =  null ;for  (ListNode list : lists) {return  res;public  static  ListNode mergeTwoListsMoreSimple (ListNode l1, ListNode l2)  {ListNode  prehead  =  new  ListNode (-1 );ListNode  prev  =  prehead;while  (l1 != null  && l2 != null ) {if  (l1.val <= l2.val) {else  {null  ? l2 : l1;return  prehead.next;
判断链表中是否有环 :定义快慢指针,从头开始;只有快指针不为空,且快指针后继不为空(即允许快指针走两步),允许前进;慢指针前进一步,快指针前进两步;快慢指针相遇,说明存在环。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  boolean  hasCycle (ListNode head)  {ListNode  slow  =  head, fast = head;while (fast != null  && fast.next != null ){if  (slow == fast) {return  true ;return  false ;
链表中环的入口节点 :找到环之后,慢节点从头开始;两节点每次都向前一步,直到相遇;相遇的节点就是环的入口节点。(解释:看图,设定首次相遇位置 P,快慢指针在到达 P 点之前,唯一一次相遇就是在链表的环的入口节点处)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22  public  ListNode EntryNodeOfLoop (ListNode pHead)  {while  (fast != null  && fast.next != null ) {if  (fast == slow) break ;if  (fast == null  || fast.next == null ) {return  null ;while  (slow != fast) {return  slow;
寻找倒数第 K 个节点 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public  ListNode FindKthToTail  (ListNode pHead, int  k)  {if  (pHead == null  || k <= 0 ) {return  null ;ListNode  fast  =  pHead;ListNode  slow  =  pHead;for  (int  i  =  0 ; i < k; i++) {if  (fast == null ) {return  null ;while  (fast != null ) {return  slow;
两链表的第一个公共节点 :
集合/哈希辅助:遍历存储第一条链表所有节点,再遍历第二条链表,挨个从集合中查找判断是否有相同节点 
链表拼接:两链表同时向后遍历,如果遍历结束,就分别换另一条链表继续遍历。如果两链表相交,则遍历过程中必然会相遇,直接返回即可;如果不相交,则必不会相遇,且一定会同时遍历结束,直接返回了null 
压栈:两链表分别压栈,依次出栈,如果节点相同,保存节点,不相同就直接返回最近保存的节点,就是答案 
 
链表相加 :
判断回文链表 :
删除有序链表中的重复元素Ⅰ :
删除有序链表中的重复元素Ⅱ :
蓝桥杯 
2024年4月11日
 
蓝桥杯,五天冲刺计划 
第十四届蓝桥杯大赛软件赛省赛Java 大学 B 组 
第十三届蓝桥杯大赛软件赛省赛Java 大学 B 组 
第十二届蓝桥杯大赛软件赛省赛Java 大学 B 组 
第十一届蓝桥杯大赛软件赛省赛Java 大学 B 组 
第十届蓝桥杯大赛软件赛省赛Java 大学 B 组 
点睛之笔 认识数据结构和算法 
数据结构:数据存储的方式    数组,字符串,树,堆,栈,队列,哈希表 算法:数据计算的方式枚举遍历,排序,二分查找,递归,回溯  
算法题类型 
数学 数组 链表 字符串 哈希表 双指针 递归 栈 队列 树 图与回溯算法 贪心 动态规划  
刷题顺序 
第一轮:数学 -> 数组 -> 链表 -> 字符串 -> 哈希表 -> 双指针 -> 递归 -> 栈 -> 队列    难度简单    50% 第二轮:数学 -> 数组 -> 链表 -> 字符串 -> 哈希表 -> 双指针 -> 递归 -> 栈 -> 队列    难度中等    50% 第三轮:分治    贪心    动态规划    二叉搜索树    图    50% 第四轮:难