力扣HOT100合集

力扣HOT100 - 1. 两数之和

 

解题思路:

解法一:暴力

class Solution {public int[] twoSum(int[] nums, int target) {int n = nums.length;for (int i = 0; i < n; i++)for (int j = i + 1; j < n; j++) {if (target == nums[i] + nums[j])return new int[] { i, j };}return new int[0];}
}

解法二:哈希表

class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> map = new HashMap<>();for (int i = 0; i < nums.length; ++i) {if (map.containsKey(target - nums[i])) {//保证返回的下标由小到大return new int[]{map.get(target - nums[i]), i};}map.put(nums[i], i);}return new int[0];}
}

力扣HOT100 - 49. 字母异位词分组

 

解题思路:

排序

注意:

返回时不能用List,因为List是抽象类,return的必须是List的具体实现,如ArrayList

class Solution {public List<List<String>> groupAnagrams(String[] strs) {Map<String, List<String>> map = new HashMap<>();for (String str : strs) {char[] array = str.toCharArray();Arrays.sort(array);String key = new String(array);List<String> list = map.getOrDefault(key, new ArrayList<String>());list.add(str);map.put(key, list);}//返回时不能用List,而必须是List的具体实现,如ArrayListreturn new ArrayList<List<String>>(map.values());}
}

力扣HOT100 - 128. 最长连续序列

 

解题思路:

注意:

1.Set不能直接排序,必须要转换成ArrayList或者LinkedList后用Collections.sort()方法进行排序。

(Queue也不能直接排序,排序方法同Set)

2.连续的序列不能只找第一个,因为不一定是最长的,需要全部遍历完才能找到最长序列。

class Solution {public int longestConsecutive(int[] nums) {if (nums.length == 0)  return 0;Set<Integer> set = new HashSet<>();for (int i = 0; i < nums.length; i++) {set.add(nums[i]);}List<Integer> list = new ArrayList<>(set);Collections.sort(list);//cnt的长度从1开始,本身长度为1int cnt = 1;int max = 0;//减一是为了避免越界for (int i = 0; i < list.size() - 1; i++) {if (list.get(i) == list.get(i + 1) - 1) {cnt++;} else {max = Math.max(cnt, max);//重置cnt的值cnt = 1;}}max = Math.max(cnt, max);return max;}
}

力扣HOT100 - 283. 移动零

 

解题思路:

双指针

指针 i 用于寻找不为零的位置

指针 j 用于寻找为零的位置

找到不为零时位置时与为零的位置进行交换,即nums[ i ]与nums[ j ]交换,使零向后移动,i 和 j 同时向下一个位置移动。

class Solution {public void moveZeroes(int[] nums) {if (nums == null) return;            int j = 0;for (int i = 0; i < nums.length; i++) {if (nums[i] != 0) {int tmp = nums[i];nums[i] = nums[j];nums[j++] = tmp;//j++所到的位置还是零}}}
}

力扣HOT100 - 11. 盛最多水的容器

 

解题思路:

双指针,从左右两边往内侧夹逼,遍历后得到最大值

class Solution {public int maxArea(int[] height) {int i = 0, j = height.length - 1, res = 0;while(i < j) {res = height[i] < height[j] ? Math.max(res, (j - i) * height[i++]): Math.max(res, (j - i) * height[j--]); }return res;}
}

力扣HOT100 - 15. 三数之和

 

解题思路:

排序 + 双指针

注意:

        在nums[ k ],nums[ i ],nums[ j ]的值与自身重复时均会进行跳过,防止重复添加。

如代码中:

        防止nums[ k ]重复:if(k>0&&nums[k]==nums[k-1]) continue;

        防止nums[ i ]重复:while(i<j&&nums[i]==nums[++i]);

        防止nums[ j ]重复:while(i<j&&nums[j]==nums[--j]);

class Solution {public List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums);List<List<Integer>> res = new ArrayList<>();for(int k = 0; k < nums.length - 2; k++){if(nums[k] > 0) break;if(k > 0 && nums[k] == nums[k - 1]) continue;int i = k + 1, j = nums.length - 1;while(i < j){int sum = nums[k] + nums[i] + nums[j];if(sum < 0){while(i < j && nums[i] == nums[++i]);} else if (sum > 0) {while(i < j && nums[j] == nums[--j]);} else {res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));while(i < j && nums[i] == nums[++i]);while(i < j && nums[j] == nums[--j]);}}}return res;}
}

力扣HOT100 - 42. 接雨水

 

解题思路:

动态规划

感觉不是很好想

class Solution {public int trap(int[] height) {int n = height.length;if (n == 0) return 0;int[] leftMax = new int[n];leftMax[0] = height[0];for (int i = 1; i < n; i++) {leftMax[i] = Math.max(leftMax[i - 1], height[i]);}int[] rightMax = new int[n];rightMax[n - 1] = height[n - 1];for (int i = n - 2; i >= 0; i--) {rightMax[i] = Math.max(rightMax[i + 1], height[i]);}int res = 0;for (int i = 0; i < n; i++) {res += Math.min(leftMax[i], rightMax[i]) - height[i];}return res;}
}

力扣HOT100 - 3. 无重复字符的最长子串

 

解题思路:

滑动窗口

注意:

left = Math.max(left,map.get(ch[i]) + 1);通过取最大值可以保证left不往回走

如果只是left = map.get(ch[i]) + 1; 在某些情况下也是正确的,但在一些特殊情况下可能会导致错误的结果。考虑以下情况:

假设字符串为 “abba”,当遍历到第二个 a 字符时,如果用 start = map.get('a') + 1;那么left将指向第一个 a 的下一个位置(设这个位置为 x ),而实际上left原先在循环到第二个 b 时就已经到了 x 的下一个位置。这样left往回走会导致错误的结果。

class Solution {public int lengthOfLongestSubstring(String s) {if(s.length() == 0) return 0;Map<Character, Integer> map = new HashMap<>();char[] ch = s.toCharArray();int max = 0;int left = 0;for(int i = 0; i < ch.length; i++) {if (map.containsKey(ch[i])) {left = Math.max(left,map.get(ch[i]) + 1);}map.put(ch[i], i);max = Math.max(max, i - left + 1);}return max;}
}

力扣HOT100 - 438. 找到字符串中所有字母异位词

 

解题思路:

滑动窗口

class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> res = new ArrayList<>();int sLen = s.length();int pLen = p.length();if (sLen < pLen) return res;// 建立两个数组存放字符串中字母出现的词频,并以此作为标准比较int[] scount = new int[26];int[] pcount = new int[26];// 当滑动窗口的首位在s[0]处时 (相当于放置滑动窗口进入数组)for (int i = 0; i < pLen; i++) {scount[s.charAt(i) - 'a']++; // 记录s中前pLen个字母的词频pcount[p.charAt(i) - 'a']++; // 记录要寻找的字符串中每个字母的词频(只用进行一次来确定)}// 判断放置处是否有异位词 (在放置时只需判断一次)if (Arrays.equals(scount, pcount)) res.add(0);// 开始让窗口进行滑动for (int i = 0; i < sLen - pLen; i++) { // i是滑动前的首位scount[s.charAt(i) - 'a']--; // 将滑动前首位的词频删去scount[s.charAt(i + pLen) - 'a']++; // 增加滑动后最后一位的词频(以此达到滑动的效果)// 判断滑动后处,是否有异位词if (Arrays.equals(scount, pcount)) res.add(i + 1);}return res;}
}

力扣HOT100 - 560. 和为k的子数组

 

解题思路:

方法一:枚举

class Solution {public int subarraySum(int[] nums, int k) {int cnt = 0;for (int start = 0; start < nums.length; start++) {int sum = 0;//注意开始位置for (int end = start; end < nums.length; end++) {sum += nums[end];if (sum == k) {cnt++;}}}return cnt;}
}

方法二:前缀和 + 哈希表优化

通过计算前缀和,我们可以将问题转化为求解两个前缀和之差等于k的情况。

假设数组的前缀和数组为prefixSum,其中prefixSum[i]表示从数组起始位置到第i个位置的元素之和。那么对于任意的两个下标i和j(i < j),如果prefixSum[j] - prefixSum[i] = k,即从第i个位置到第j个位置的元素之和等于k,那么说明从第i+1个位置到第j个位置的连续子数组的和为k。

通过遍历数组,计算每个位置的前缀和,并使用一个哈希表来存储每个前缀和出现的次数。在遍历的过程中,我们检查是否存在prefixSum[j] - k的前缀和,如果存在,说明从某个位置到当前位置的连续子数组的和为k,我们将对应的次数累加到结果中。

public class Solution {public static int subarraySum(int[] nums, int k) {int count = 0;int sum = 0;Map<Integer, Integer> map = new HashMap<>();map.put(0, 1); // 初始化前缀和为0的次数为1for (int i = 0; i < nums.length; i++) {sum += nums[i];if (map.containsKey(sum - k)) {count += map.get(sum - k);}map.put(sum, map.getOrDefault(sum, 0) + 1);}return count;}
}

力扣HOT100 - 239. 滑动窗口最大值

 

解题思路:

class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if(nums.length == 0 || k == 0) return new int[0];Deque<Integer> deque = new LinkedList<>();int[] res = new int[nums.length - k + 1];// 未形成窗口for(int i = 0; i < k; i++) {while(!deque.isEmpty() && deque.peekLast() < nums[i])deque.removeLast();deque.addLast(nums[i]);}res[0] = deque.peekFirst();// 形成窗口后for(int i = k; i < nums.length; i++) {//因为窗口要滑动,所以如果双端队列的最大值就是数组的第一个元素,会被滑动出去if(deque.peekFirst() == nums[i - k])deque.removeFirst();while(!deque.isEmpty() && deque.peekLast() < nums[i])deque.removeLast();deque.addLast(nums[i]);res[i - k + 1] = deque.peekFirst();}return res;}
}

力扣HOT100 - 76. 最小覆盖子串

 

解题思路:

class Solution {public String minWindow(String s, String t) {if (s == null || s.isEmpty() || t == null || t.isEmpty() || s.length() < t.length())return "";Map<Character, Integer> tmap = new HashMap<>();Map<Character, Integer> window = new HashMap<>();// 记录 t 中每个字符的出现次数for (char c : t.toCharArray())tmap.put(c, tmap.getOrDefault(c, 0) + 1);int left = 0, right = 0;// 窗口的左右边界int valid = 0;// 已经匹配上的字符数量int start = 0, minLen = Integer.MAX_VALUE;// 最小窗口的起始位置和长度while (right < s.length()) {char r = s.charAt(right);right++;if (tmap.containsKey(r)) {window.put(r, window.getOrDefault(r, 0) + 1);//不能用==,window.get(r) 和 tmap.get(r) 都返回的是 Integer 类型的对象。当使用 == 进行比较时,实际上比较的是两个 Integer 对象的引用,而非它们的值。if (window.get(r).equals(tmap.get(r)))valid++;}while (valid == tmap.size()) {if (right - left < minLen) {start = left;minLen = right - left;}char l = s.charAt(left);left++;if (tmap.containsKey(l)) {window.put(l, window.get(l) - 1);if (window.get(l) < tmap.get(l))valid--;}}}return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);}
}

力扣HOT100 - 53. 最大子数组和

 

解题思路:

class Solution {public int maxSubArray(int[] nums) {int res = Integer.MIN_VALUE;int tempTotal = 0;for(int i=0;i<nums.length;i++){tempTotal+=nums[i];res = Math.max(res,tempTotal);// 如果和小于0,就重置为0if(tempTotal<0) tempTotal = 0;}return res;}
}

力扣HOT100 - 56. 合并区间

 

解题思路:

class Solution {public int[][] merge(int[][] intervals) {// 先按照区间起始位置排序Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]);int[][] res = new int[intervals.length][2];int idx = -1;for (int[] interval : intervals) {//直接加入的情况,空二维数组第一次加入元素或二维数组中最后一个区间的右端小于新区间的左端,那么一定不重合if (idx == -1 || res[idx][1] < interval[0])res[++idx] = interval;//合并区间的两种情况//二维数组中最后一个区间的右端大于等于新区间的左端//或最后一个区间整体包含新区间(考虑这两种情况所以才取最大值)else{res[idx][1] = Math.max(interval[1], res[idx][1]);}}return Arrays.copyOf(res, idx + 1);}
}

力扣HOT100 - 189. 轮转数组

 

解题思路:

三次反转。

先反转一次,再根据 k 拆分成两部分各反转一次。

class Solution {public void rotate(int[] nums, int k) {k %= nums.length;reverse(nums, 0, nums.length - 1);reverse(nums, 0, k - 1);reverse(nums, k, nums.length - 1);}public void reverse(int[] nums, int start, int end) {while (start < end) {int temp = nums[start];nums[start] = nums[end];nums[end] = temp;start++;end--;}}
}

力扣HOT100 - 238. 除自身以外数组的乘积

 

解题思路:

当前位置的结果就是它左部分的乘积再乘以它右部分的乘积。因此需要进行两次遍历,第一次遍历用于求左部分的乘积,第二次遍历在求右部分的乘积的同时,再将最后的计算结果一起求出来。

class Solution {public int[] productExceptSelf(int[] nums) {int len = nums.length;if (len == 0)return new int[0];int[] ans = new int[len];ans[0] = 1;int tmp = 1;//左半部分乘积for (int i = 1; i < len; i++) {ans[i] = ans[i - 1] * nums[i - 1];}//右半部分乘积,巧妙地使用tmpfor (int i = len - 2; i >= 0; i--) {tmp *= nums[i + 1];ans[i] *= tmp;}return ans;}
}

力扣HOT100 - 41. 缺失的第一个正数

 

解题思路:

原地哈希

就相当于,让每个数字n都回到下标为n-1的家里。

而那些没有回到家里的就成了孤魂野鬼流浪在外,他们要么是根本就没有自己的家(数字小于等于0或者大于nums.size()),要么是自己的家被别人占领了(出现了重复)。

class Solution {public int firstMissingPositive(int[] nums) {int len = nums.length;for (int i = 0; i < len; i++) {// 不能使用nums[i]-1!=i来判断,外面同时套了一层nums[]while (nums[i] > 0 && nums[i] <= len && nums[nums[i] - 1] != nums[i])swap(nums, i, nums[i] - 1);}for (int i = 0; i < len; i++) {if (nums[i] != i + 1)return i + 1;}return len + 1;}public void swap(int[] nums, int idx1, int idx2) {int tmp = nums[idx1];nums[idx1] = nums[idx2];nums[idx2] = tmp;}
}

力扣HOT100 - 73. 矩阵置零

 

解题思路:

题目要求使用原地算法

在原地算法中,输入数据通常在内存中直接被修改,而不需要额外的辅助数据结构来存储中间结果。原地算法的一个常见应用是在数组或列表上进行操作,而不是创建新的数组或列表来存储结果。

class Solution {public void setZeroes(int[][] matrix) {int row = matrix.length; // 矩阵的行数int col = matrix[0].length; // 矩阵的列数boolean row0_flag = false; // 标记第一行是否有零boolean col0_flag = false; // 标记第一列是否有零// 检查第一行是否有零,遍历第一行需要知道有多少列for (int j = 0; j < col; j++) {if (matrix[0][j] == 0) {row0_flag = true;break;}}// 检查第一列是否有零,遍历第一列需要知道有多少行for (int i = 0; i < row; i++) {if (matrix[i][0] == 0) {col0_flag = true;break;}}// 使用第一行和第一列作为标志位for (int i = 1; i < row; i++) {for (int j = 1; j < col; j++) {if (matrix[i][j] == 0) {matrix[i][0] = matrix[0][j] = 0; // 如果元素为零,则将对应的第一行和第一列的元素设置为零}}}// 根据第一行和第一列的标志位,将矩阵中的元素置零for (int i = 1; i < row; i++) {for (int j = 1; j < col; j++) {if (matrix[i][0] == 0 || matrix[0][j] == 0) {matrix[i][j] = 0; // 如果第一行或第一列的元素为零,则将当前元素置零}}}// 如果第一行有零,则将第一行所有元素置零,遍历第一行需要知道有多少列if (row0_flag) {for (int j = 0; j < col; j++) {matrix[0][j] = 0;}}// 如果第一列有零,则将第一列所有元素置零,遍历第一列需要知道有多少行if (col0_flag) {for (int i = 0; i < row; i++) {matrix[i][0] = 0;}} }
}

力扣HOT100 - 54. 螺旋矩阵

 

解题思路:

设置四个边界

class Solution {public List<Integer> spiralOrder(int[][] matrix) {if (matrix.length == 0) return new ArrayList<Integer>();int l = 0;int r = matrix[0].length - 1;int t = 0;int b = matrix.length - 1;List<Integer> res = new ArrayList<>();while (true) {for (int i = l; i <= r; i++) res.add(matrix[t][i]);if (++t > b) break;for (int i = t; i <= b; i++) res.add(matrix[i][r]);if (--r < l) break;for (int i = r; i >= l; i--) res.add(matrix[b][i]);if (--b < t) break;for (int i = b; i >= t; i--) res.add(matrix[i][l]);if (++l > r) break;}return res;}
}

力扣HOT100 - 48. 旋转图像

 

解题思路:

要求原地旋转

可以先上下翻转,再沿主对角线反转(左上到右下的对角线)

class Solution {public void rotate(int[][] matrix) {int n = matrix.length;// 上下翻转for (int i = 0; i < n / 2; i++) {for (int j = 0; j < n; j++) {int tmp = matrix[i][j];matrix[i][j] = matrix[n - i - 1][j];matrix[n - i - 1][j] = tmp;}}// 沿主对角线(\)翻转for (int i = 0; i < n; i++) {for (int j = 0; j < i; j++) {int tmp = matrix[i][j];matrix[i][j] = matrix[j][i];matrix[j][i] = tmp;}}}
}

力扣HOT100 - 240. 搜索二维矩阵 II

 

解题思路:

从左下角开始,根据条件删除行和列。

class Solution {public boolean searchMatrix(int[][] matrix, int target) {int row = matrix.length - 1;int col = matrix[0].length - 1;int l = 0;while (row >= 0 && l <= col) {if (target < matrix[row][l]) {row--;} else if (target > matrix[row][l]) {l++;} else {return true;}}return false;}
}

力扣HOT100 - 160. 相交链表

 

解题思路:

/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA == null || headB == null) return null;ListNode pa = headA;ListNode pb = headB;while (pa != pb) {pa = (pa != null) ? pa.next : headB;pb = (pb != null) ? pb.next : headA;if (pa == null && pb == null) return null;}return pa;}
}

力扣HOT100 - 206. 反转链表

 

解题思路:

迭代(双指针)

class Solution {public ListNode reverseList(ListNode head) {ListNode cur = head, pre = null;while(cur != null) {ListNode tmp = cur.next; // 暂存后继节点 cur.nextcur.next = pre;          // 修改 next 引用指向pre = cur;               // pre 暂存 curcur = tmp;               // cur 访问下一节点}return pre;}
}

力扣HOT100 - 234. 回文链表

 

解题思路:

class Solution {public boolean isPalindrome(ListNode head) {List<Integer> list = new ArrayList<Integer>();// 将链表的值复制到数组中ListNode cur = head;while (cur != null) {list.add(cur.val);cur = cur.next;}// 使用双指针判断是否回文int l = 0;int r = list.size() - 1;while (l < r) {if (!list.get(l).equals(list.get(r))) {return false;}l++;r--;}return true;}
}

力扣HOT100 - 141. 环形链表

 

解题思路:

public class Solution {public boolean hasCycle(ListNode head) {Set<ListNode> set = new HashSet<>();while (head != null) {if (!set.add(head)) {return true;}head = head.next;}return false;}
}

力扣HOT100 - 142. 环形链表 II

 

解题思路:

public class Solution {public ListNode detectCycle(ListNode head) {Set<ListNode> set = new HashSet<>();while (head != null) {if (!set.add(head)) {return head;}head = head.next;}return null;}
}

力扣HOT100 - 21. 合并两个有序链表

 

解题思路:

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode dum = new ListNode(0), cur = dum;while (list1 != null && list2 != null) {if (list1.val <= list2.val) {cur.next = list1;list1 = list1.next;} else {cur.next = list2;list2 = list2.next;}cur = cur.next;}cur.next = list1 != null ? list1 : list2;return dum.next;}
}

力扣HOT100 - 2. 两数相加

 

解题思路:

缺位的节点进行补零处理,如973+23补充为973+023

注意相加的进位问题

class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode head = null, tail = null;int carry = 0;while (l1 != null || l2 != null) {int n1 = l1 != null ? l1.val : 0;int n2 = l2 != null ? l2.val : 0;int sum = n1 + n2 + carry;if (head == null) {head = tail = new ListNode(sum % 10);} else {tail.next = new ListNode(sum % 10);tail = tail.next;}carry = sum / 10;if (l1 != null) l1 = l1.next;if (l2 != null) l2 = l2.next;}if (carry > 0) tail.next = new ListNode(carry);return head;}
}

力扣HOT100 - 19. 删除链表的倒数第N个节点

 

解题思路:

链表题目:哑节点、栈、快慢指针(双指针)

方法一:计算链表长度

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dum = new ListNode(0, head);int len = getLen(head);ListNode cur = dum;for (int i = 0; i < len - n; i++) {cur = cur.next;}cur.next = cur.next.next;return dum.next;}public int getLen(ListNode head) {int len = 0;while (head != null) {head = head.next;len++;}return len;}
}

方法二:栈

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dum = new ListNode(0, head);Deque<ListNode> stack = new LinkedList<>();ListNode cur=dum;while(cur!=null){stack.push(cur);cur=cur.next;}for(int i=0;i<n;i++){stack.pop();}ListNode pre=stack.peek();pre.next=pre.next.next;return dum.next;}
}

方法三:快慢指针(双指针)

注意fast从head开始,而不是dum

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dum = new ListNode(0, head);ListNode fast=head;ListNode slow=dum;for(int i=0;i<n;i++){fast=fast.next;}while(fast!=null){slow=slow.next;fast=fast.next;}slow.next=slow.next.next;return dum.next;}
}

力扣HOT100 - 24. 两两交换链表中的节点

 

解题思路:

递归

class Solution {public ListNode swapPairs(ListNode head) {if (head == null || head.next == null) {return head;}ListNode newHead = head.next;head.next = swapPairs(newHead.next);newHead.next = head;return newHead;}
}

力扣HOT100 - 25. K 个一组翻转链表

 

解题思路:

class Solution {public ListNode reverseKGroup(ListNode head, int k) {ListNode dum = new ListNode(0, head);ListNode pre = dum;ListNode end = dum;while (end.next != null) {for (int i = 0; i < k && end != null; i++) {end = end.next;}if (end == null) break;ListNode start = pre.next;ListNode next = end.next;end.next = null;pre.next = reverse(start);start.next = next;pre = start;end = start;}return dum.next;}public ListNode reverse(ListNode head) {ListNode pre = null;ListNode cur = head;while (cur != null) {ListNode tmp = cur.next;cur.next = pre;pre = cur;cur = tmp;}return pre;}
}

力扣HOT100 - 138. 随机链表的复制

 

解题思路:

class Solution {public Node copyRandomList(Node head) {if(head==null) return null;Node p = head;//第一步,在每个原节点后面创建一个新节点//1->1'->2->2'->3->3'while(p!=null) {Node newNode = new Node(p.val);newNode.next = p.next;p.next = newNode;p = newNode.next;}p = head;//第二步,设置新节点的随机节点while(p!=null) {if(p.random!=null) {p.next.random = p.random.next;}p = p.next.next;}p = head;Node anotherNode = new Node(-1);//定义一个另外的新节点,给它赋值为-1Node cur = anotherNode;//第三步,将两个链表分离while(p!=null) {cur.next = p.next;cur = cur.next;p.next = cur.next;p = p.next;}return anotherNode.next;}
}	

注意:

Node p=head;与Node p=new Node(head.val);存在区别

前者的p为一个指向head对象的引用,换句话说,p和head 指向同一个对象,它们共享相同的引用,后者则创建一个全新的Node节点,p与head的val值相同。

力扣HOT100 - 148. 排序链表

 

解题思路:

归并排序

class Solution {public ListNode sortList(ListNode head) {if (head == null || head.next == null) return head;ListNode fast = head.next, slow = head;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}ListNode temp = slow.next;slow.next = null;ListNode left = sortList(head);ListNode right = sortList(temp);ListNode dum = new ListNode(0);ListNode cur = dum;while (left != null && right != null) {if (left.val < right.val) {cur.next = left;left = left.next;} else {cur.next = right;right = right.next;}cur = cur.next;}cur.next = left != null ? left : right;return dum.next;}
}

力扣HOT100 - 23. 合并K个升序链表

 

解题思路:

只要会合并两个升序链表,合并K个做法类似。

class Solution {public ListNode mergeKLists(ListNode[] lists) {ListNode res = null;for (int i = 0; i < lists.length; i++) {res = merge(res, lists[i]);}return res;}public ListNode merge(ListNode l1, ListNode l2) {if (l1 == null || l2 == null)return l1 == null ? l2 : l1;ListNode dum = new ListNode(0);ListNode cur = dum;while (l1 != null && l2 != null) {if (l1.val < l2.val) {cur.next = l1;l1 = l1.next;} else {cur.next = l2;l2 = l2.next;}cur = cur.next;}cur.next = l1 != null ? l1 : l2;return dum.next;}
}

力扣HOT100 - 146. LRU缓存

 

解题思路:

哈希表 + 双向链表

public class LRUCache {class DLinkedNode {int key;int value;DLinkedNode prev;DLinkedNode next;public DLinkedNode() {}public DLinkedNode(int _key, int _value) {key = _key; value = _value;}}private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();private int size;private int capacity;private DLinkedNode head, tail;public LRUCache(int capacity) {this.size = 0;this.capacity = capacity;// 使用伪头部和伪尾部节点head = new DLinkedNode();tail = new DLinkedNode();head.next = tail;tail.prev = head;}public int get(int key) {DLinkedNode node = cache.get(key);if (node == null) {return -1;}// 如果 key 存在,先通过哈希表定位,再移到头部moveToHead(node);return node.value;}public void put(int key, int value) {DLinkedNode node = cache.get(key);if (node == null) {// 如果 key 不存在,创建一个新的节点DLinkedNode newNode = new DLinkedNode(key, value);// 添加进哈希表cache.put(key, newNode);// 添加至双向链表的头部addToHead(newNode);++size;if (size > capacity) {// 如果超出容量,删除双向链表的尾部节点DLinkedNode tail = removeTail();// 删除哈希表中对应的项cache.remove(tail.key);--size;}}else {// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部node.value = value;moveToHead(node);}}private void addToHead(DLinkedNode node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void removeNode(DLinkedNode node) {node.prev.next = node.next;node.next.prev = node.prev;}private void moveToHead(DLinkedNode node) {removeNode(node);addToHead(node);}private DLinkedNode removeTail() {DLinkedNode res = tail.prev;removeNode(res);return res;}
}

力扣HOT100 - 94. 二叉树的中序遍历

 

解题思路:

递归

class Solution {List<Integer> list = new ArrayList<>();public List<Integer> inorderTraversal(TreeNode root) {recur(root);return list;}public void recur(TreeNode root) {if (root == null) return;recur(root.left);list.add(root.val);recur(root.right);}
}

力扣HOT100 - 104. 二叉树的最大深度

 

解题思路:

class Solution {public int maxDepth(TreeNode root) {if (root == null) return 0;return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;}
}

力扣HOT100 - 226. 翻转二叉树

 

解题思路:

class Solution {public TreeNode invertTree(TreeNode root) {if (root == null) return null;TreeNode left = invertTree(root.left);TreeNode right = invertTree(root.right);root.left = right;root.right = left;return root;}
}

力扣HOT100 - 101. 对称二叉树

 

解题思路:

class Solution {public boolean isSymmetric(TreeNode root) {if(root == null) return true;return recur(root.left, root.right);}boolean recur(TreeNode L, TreeNode R) {if (L == null && R == null) return true;if (L == null || R == null || L.val != R.val) return false;return recur(L.left, R.right) && recur(L.right, R.left);}
}

力扣HOT100 - 543. 二叉树的直径

 

解题思路:

class Solution {int ans;//记录节点数public int diameterOfBinaryTree(TreeNode root) {ans = 1;depth(root);return ans - 1;//节点数减 1 就是路径长度}public int depth(TreeNode root) {if (root == null) return 0;int l = depth(root.left);int r = depth(root.right);ans = Math.max(ans, l + r + 1);return Math.max(l, r) + 1;}
}

力扣HOT100 - 102. 二叉树的层序遍历

 

解题思路:

广度优先遍历

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> res = new ArrayList<>();Deque<TreeNode> queue = new LinkedList<>();if (root != null) queue.add(root);while (!queue.isEmpty()) {List<Integer> list = new ArrayList<>();for (int i = queue.size(); i > 0; i--) {TreeNode tmp = queue.pop();if (tmp.left != null) queue.add(tmp.left);if (tmp.right != null) queue.add(tmp.right);list.add(tmp.val);}res.add(list);}return res;}
}

力扣HOT100 - 108. 将有序数组转换为二叉搜索树

 

解题思路:

二叉搜索树一般使用中序遍历

class Solution {public TreeNode sortedArrayToBST(int[] nums) {return helper(nums,0,nums.length-1);}public TreeNode helper(int[] nums,int left,int right){if(left>right) return null;//确定根节点//总是选择中间位置左边的数字作为根节点//也可以用 int mid = (left + right + 1) / 2; 总是选择中间位置右边的数字作为根节点int mid=(left+right)/2;TreeNode root=new TreeNode(nums[mid]);root.left=helper(nums,left,mid-1);root.right=helper(nums,mid+1,right);return root;}
}

力扣HOT100 - 98. 验证二叉搜索树

 

解题思路:

class Solution {public boolean isValidBST(TreeNode root) {return recur(root,Long.MIN_VALUE,Long.MAX_VALUE);}public boolean recur(TreeNode root,long lower,long upper){if(root==null) return true;if(root.val<=lower||root.val>=upper) return false;return recur(root.left,lower,root.val)&&recur(root.right,root.val,upper);}
}

力扣HOT100 - 230. 二叉搜索树中第K小的元素

 

解题思路:

class Solution {List<Integer> list = new ArrayList<>();public int kthSmallest(TreeNode root, int k) {dfs(root);return list.get(k - 1);}public void dfs(TreeNode root) {if (root == null) return;dfs(root.left);list.add(root.val);dfs(root.right);}
}

力扣HOT100 - 199. 二叉树的右视图

 

解题思路:

相当于层序遍历,然后取每一层的最后一个节点。

class Solution {public List<Integer> rightSideView(TreeNode root) {if (root == null) return new ArrayList<Integer>();Queue<TreeNode> queue = new LinkedList<>();List<Integer> list = new ArrayList<>();queue.add(root);while (!queue.isEmpty()) {TreeNode node = null;for (int i = queue.size(); i > 0; i--) {node = queue.poll();if (node.left != null) queue.add(node.left);if (node.right != null) queue.add(node.right);}list.add(node.val);}return list;}
}

力扣HOT100 - 114. 二叉树展开为链表

 

解题思路:

class Solution {List<TreeNode> list = new ArrayList<>();public void flatten(TreeNode root) {recur(root);for (int i = 1; i < list.size(); i++) {TreeNode pre = list.get(i - 1);TreeNode cur = list.get(i);pre.left = null;pre.right = cur;}}public void recur(TreeNode root) {if (root == null) return;list.add(root);recur(root.left);recur(root.right);}
}

力扣HOT100 - 105. 从前序与中序遍历序列构造二叉树

 

解题思路:

分治

以中序遍历为参照,用前序遍历的节点构建二叉树。

root + 1 + index - left表示前序遍历右子树的开始节点,即当前节点的下一个节点+左子树长度。

class Solution {int[] preorder;HashMap<Integer, Integer> map = new HashMap<>();public TreeNode buildTree(int[] preorder, int[] inorder) {this.preorder = preorder;for (int i = 0; i < inorder.length; i++) {map.put(inorder[i], i);}return recur(0, 0, inorder.length - 1);}TreeNode recur(int root, int left, int right) {if (left > right) return null;TreeNode node = new TreeNode(preorder[root]);int index = map.get(preorder[root]);node.left = recur(root + 1, left, index - 1);node.right = recur(root + 1 + index - left, index + 1, right);return node;}
}

力扣HOT100 - 437. 路径总和 III

 

解题思路:

深度优先搜索

搜索所有节点的情况。

class Solution {public int pathSum(TreeNode root, long targetSum) {if (root == null) return 0;int res = recur(root, targetSum);res += pathSum(root.left, targetSum);res += pathSum(root.right, targetSum);return res;}public int recur(TreeNode root, long targetSum) {int res = 0;//以新节点为起点,res置0if (root == null) return 0;int val = root.val;if (val == targetSum) res++;res += recur(root.left, targetSum - val);res += recur(root.right, targetSum - val);return res;}
}

力扣HOT100 - 236. 二叉树的最近公共祖先

 

解题思路:

dfs

节点p,q异侧时,节点root为它们的公共祖先。

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if (root == null || p == root || q == root) return root;TreeNode left = lowestCommonAncestor(root.left, p, q);TreeNode right = lowestCommonAncestor(root.right, p, q);if (left == null && right == null) return null;if (left == null) return right;if (right == null) return left;return root;}
}

力扣HOT100 - 124. 二叉树中的最大路径和

 

解题思路:

class Solution {int max = Integer.MIN_VALUE;public int maxPathSum(TreeNode root) {maxGain(root);return max;}public int maxGain(TreeNode node) {if (node == null) return 0;int leftGain = Math.max(maxGain(node.left), 0);int rightGain = Math.max(maxGain(node.right), 0);int priceNewPath = node.val + leftGain + rightGain;max = Math.max(priceNewPath, max);return node.val + Math.max(leftGain, rightGain);}
}

力扣HOT100 - 200. 岛屿数量

 

解题思路:

岛屿题目一般使用dfs。

1.判断是否越界

2.用0,1,2三个状态标识当前格子的状态(三个状态比两个状态更清晰)

3.向周围四个方向遍历

class Solution {public int numIslands(char[][] grid) {int cnt = 0;for (int i = 0; i < grid.length; i++) {for (int j = 0; j < grid[0].length; j++) {if (grid[i][j] == '1') {dfs(grid, i, j);cnt++;}}}return cnt;}public void dfs(char[][] grid, int i, int j) {if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0' || grid[i][j] == '2') return;grid[i][j] = '2';dfs(grid, i + 1, j);dfs(grid, i - 1, j);dfs(grid, i, j + 1);dfs(grid, i, j - 1);}
}

力扣HOT100 - 994. 腐烂的橘子

 

解题思路:

因为要记录轮数(分钟数),所以不能一口气遍历到底,所以不能用深搜(bfs),而要用广搜(bfs,层序遍历)。

先记录下新鲜橘子数,并用一个队列记录腐烂橘子的坐标。

每轮遍历腐烂橘子(使用过的腐烂橘子需要出队),并向四周影响,使得四周的新鲜橘子变为腐烂橘子(新鲜橘子数减1,队列中加入新的腐烂橘子的坐标)。

class Solution {public int orangesRotting(int[][] grid) {Queue<int[]> queue = new LinkedList<>();int fresh = 0;for (int r = 0; r < grid.length; r++) {for (int c = 0; c < grid[0].length; c++) {if (grid[r][c] == 1) fresh++;else if (grid[r][c] == 2) queue.add(new int[] { r, c });}}int minutes = 0;while (fresh > 0 && !queue.isEmpty()) {minutes++;int n = queue.size();// for循环中queue大小不断变化,需要提前暂存for (int i = 0; i < n; i++) {int[] orange = queue.poll();int r = orange[0];int c = orange[1];if (r - 1 >= 0 && grid[r - 1][c] == 1) {grid[r - 1][c] = 2;fresh--;queue.add(new int[] { r - 1, c });}if (r + 1 < grid.length && grid[r + 1][c] == 1) {grid[r + 1][c] = 2;fresh--;queue.add(new int[] { r + 1, c });}if (c - 1 >= 0 && grid[r][c - 1] == 1) {grid[r][c - 1] = 2;fresh--;queue.add(new int[] { r, c - 1 });}if (c + 1 < grid[0].length && grid[r][c + 1] == 1) {grid[r][c + 1] = 2;fresh--;queue.add(new int[] { r, c + 1 });}}}if (fresh > 0) return -1;else return minutes;}
}

力扣HOT100 - 207. 课程表

 

解题思路:

class Solution {public boolean canFinish(int numCourses, int[][] prerequisites) {int[] inDegree = new int[numCourses];//存每个结点的入度List<List<Integer>> res = new ArrayList<>();//存结点之间依赖关系Queue<Integer> queue = new LinkedList<>();//初始化二维List集合for(int i = 0; i < numCourses; i++)res.add(new ArrayList<>());//取出每一对结点for(int[] temp : prerequisites){inDegree[temp[0]]++;res.get(temp[1]).add(temp[0]);}//先把所有入度为0的结点加入队列for(int i = 0; i < numCourses; i++)if(inDegree[i] == 0) queue.add(i);while(!queue.isEmpty()){int pre = queue.poll();numCourses--;//根据依赖关系,把入度-1for(int cur : res.get(pre)){if(--inDegree[cur] == 0)queue.add(cur);}}return numCourses == 0;}
}

力扣HOT100 208. 实现Trie(前缀树)

 

解题思路:

class Trie {private Trie[] children; // 存储子节点的数组private boolean isEnd; // 记录是否为单词结尾public Trie() {children = new Trie[26]; // 数组大小为26,代表26个小写字母isEnd = false;}public void insert(String word) {Trie node = this; // 从根节点开始for (int i = 0; i < word.length(); i++) {char ch = word.charAt(i);int index = ch - 'a'; // 计算字母对应的索引if (node.children[index] == null) {node.children[index] = new Trie(); // 如果当前节点的子节点为空,创建一个新节点}node = node.children[index]; // 移动到子节点}node.isEnd = true; // 标记当前节点为单词结尾}public boolean search(String word) {Trie node = searchPrefix(word); // 查找前缀return node != null && node.isEnd; // 判断是否找到前缀并且是否为单词结尾}public boolean startsWith(String prefix) {return searchPrefix(prefix) != null; // 判断是否找到前缀}private Trie searchPrefix(String prefix) {Trie node = this; // 从根节点开始for (int i = 0; i < prefix.length(); i++) {char ch = prefix.charAt(i);int index = ch - 'a'; // 计算字母对应的索引if (node.children[index] == null) {return null; // 如果当前节点的子节点为空,返回null}node = node.children[index]; // 移动到子节点}return node; // 返回最后一个节点}
}

力扣HOT100 - 46. 全排列

 

解题思路:

回溯

假设给定数组nums为[1, 2, 3],首先将其转换为List<Integer>类型的output为[1, 2, 3]。

在backtrack方法中,初始时first为0,所以进入第一个for循环,交换output中第一个元素和自身,然后递归调用backtrack方法,此时first为1,再次进入for循环,交换output中第二个元素(即2)和自身。这样得到的output为[1, 2, 3],添加到结果集中。

接着回到第一个for循环,再次交换output中第一个元素和自身,此时成为[2, 1, 3],再次递归调用backtrack方法,得到的output为[2, 1, 3],添加到结果集中。

依次类推,通过不断交换元素的位置和递归调用backtrack方法,可以生成所有可能的排列组合。最终得到的结果为[[1, 2, 3], [2, 1, 3], [3, 1, 2], [1, 3, 2], [2, 3, 1], [3, 2, 1]],即给定数组[1, 2, 3]的全排列结果。

class Solution {public List<List<Integer>> permute(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();List<Integer> output = new ArrayList<>();for (int num : nums) {output.add(num);}int n = nums.length;backtrack(n, output, res, 0);return res;}public void backtrack(int n, List<Integer> output, List<List<Integer>> res, int first) {if (first == n)res.add(new ArrayList<Integer>(output));for (int i = first; i < n; i++) {Collections.swap(output, first, i);backtrack(n, output, res, first + 1);Collections.swap(output, first, i);}}
}

力扣HOT100 - 78. 子集

 

解题思路:

class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> lists = new ArrayList<>(); // 解集lists.add(new ArrayList<Integer>()); // 首先将空集加入解集中for(int i = 0; i < nums.length; i++){int size = lists.size(); // 当前子集数for(int j = 0; j < size; j++){ List<Integer> newList = new ArrayList<>(lists.get(j));// 拷贝所有子集newList.add(nums[i]); // 向拷贝的子集中加入当前数形成新的子集lists.add(newList); // 向lists中加入新子集}}return lists;}
}

力扣HOT100 - 17. 电话号码的字母组合

 

解题思路:
 

class Solution {public List<String> letterCombinations(String digits) {List<String> combinations = new ArrayList<String>();if (digits.length() == 0) {return combinations;}Map<Character, String> phoneMap = new HashMap<Character, String>() {{put('2', "abc");put('3', "def");put('4', "ghi");put('5', "jkl");put('6', "mno");put('7', "pqrs");put('8', "tuv");put('9', "wxyz");}};backtrack(combinations, phoneMap, digits, 0, new StringBuffer());return combinations;}public void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {if (index == digits.length()) {combinations.add(combination.toString());} else {char digit = digits.charAt(index);String letters = phoneMap.get(digit);int lettersCount = letters.length();for (int i = 0; i < lettersCount; i++) {combination.append(letters.charAt(i));backtrack(combinations, phoneMap, digits, index + 1, combination);combination.deleteCharAt(index);}}}
}

力扣HOT100 - 39. 组合总和

 

解题思路:

class Solution {public List<List<Integer>> combinationSum(int[] candidates, int target) {int len = candidates.length;List<List<Integer>> res = new ArrayList<>();if (len == 0) return res;Deque<Integer> path = new ArrayDeque<>();dfs(candidates, 0, len, target, path, res);return res;}private void dfs(int[] candidates, int begin, int len, int target, Deque<Integer> path, List<List<Integer>> res) {if (target < 0) return;if (target == 0) {res.add(new ArrayList<>(path));return;}//重点理解for (int i = begin; i < len; i++) {path.addLast(candidates[i]);dfs(candidates, i, len, target - candidates[i], path, res);path.removeLast();}}
}

力扣HOT100 - 22. 括号生成

 

解题思路:

class Solution {List<String> res = new ArrayList<>();public List<String> generateParenthesis(int n) {if (n <= 0) return res;getParenthesis("", n, n);return res;}private void getParenthesis(String str, int left, int right) {if (left == 0 && right == 0) {res.add(str);return;}if (left == right) {// 剩余左右括号数相等,下一个只能用左括号getParenthesis(str + "(", left - 1, right);} else if (left < right) {// 剩余左括号小于右括号,下一个可以用左括号也可以用右括号if (left > 0) getParenthesis(str + "(", left - 1, right);if (right > 0) getParenthesis(str + ")", left, right - 1);}}
}

力扣HOT100 - 79. 单词搜索

 

解题思路:

深度优先搜索(DFS)+ 剪枝。

class Solution {public boolean exist(char[][] board, String word) {char[] words = word.toCharArray();for(int i = 0; i < board.length; i++) {for(int j = 0; j < board[0].length; j++) {if (dfs(board, words, i, j, 0)) return true;}}return false;}boolean dfs(char[][] board, char[] word, int i, int j, int k) {if (i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;if (k == word.length - 1) return true;board[i][j] = '\0';boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);board[i][j] = word[k];return res;}
}

力扣HOT100 - 131. 分割回文串

 

解题思路:

class Solution {List<List<String>> res = new ArrayList<>();List<String> path=new ArrayList<>();public List<List<String>> partition(String s) {backtrack(s,0);return res;}public void backtrack(String s,int startIndex){if(startIndex==s.length()){res.add(new ArrayList<>(path));return;}for(int i=startIndex+1;i<=s.length();i++){String substring=s.substring(startIndex,i);boolean flag=ishuiwen(substring);//如果不是回文,那直接这条树枝全废了,也不用递归了,去同层的下一个节点了。// 比如第一刀切出来个aab 已经不是回文了,那后面的bc 再怎么切也没用了。// 所以直接continue,到切aabb去了if(!flag) continue;path.add(substring);backtrack(s,i);path.remove(path.size()-1);}}boolean ishuiwen(String s){int i=0;int j=s.length()-1;while(i<j){if(s.charAt(i)!=s.charAt(j)) return false;i++;j--;}return true;}
}

力扣HOT100 - 51. N 皇后

 

解题思路:

class Solution {public List<List<String>> solveNQueens(int n) {//定义一个返回结果的集合List<List<String>> res = new ArrayList<>();//定义一个存储皇后的集合int[] queens = new int[n];//填充数组queens[]中的每个元素都是-1//queens={-1,-1,-1...-1}Arrays.fill(queens, -1);//定义一个变量,来记录当前元素所在的列,并将他所在的列标记为不可放元素Set<Integer> columns = new HashSet<>();//定义一个变量,来记录当前元素所在的左对角线,并将他所在的左对角线标记为不可放元素Set<Integer> diagonals1= new HashSet<>();//定义一个变量,来纪律当前元素所在的右对角线,并将他所在的右对角线标记为不可放元素Set<Integer> diagonals2 = new HashSet<>();//深度优先搜索方法dfs(res, queens, n, 0, columns,diagonals1,diagonals2);return res;}public void dfs(List<List<String>> res, int[] queens,int n,int row,  Set<Integer> columns,Set<Integer> diagonals1,Set<Integer> diagonals2){//如果当前遍历到最后一行,就说明存在一个解法//所以将皇后的位置,存放入结果中if(row == n){//用来将当前的N行N列中的元素所在的位置结果,转换格式List<String> board = generateBoard(queens, n);//将符合条件的结果添加进返回结果集中res.add(board);}else{//遍历所有行for(int i = 0; i < n; i++){//用来标记,当前行元素所在的列,都不可放元素if(columns.contains(i)){continue;}//去除左对角线上的所有元素//row 表示行,i表示列int diagonal1 = row-i;if(diagonals1.contains(diagonal1)){continue;}//去除右对角线上的元素int diagonal2 = row + i;if(diagonals2.contains(diagonal2)){continue;}//经过上面的三次排除,就可以找到元素在当前行的哪一列的位置。//选第一行的第几列,也可以叫单元格所在的位置queens[row] = i;//把选中的单元格加入到,去除列的集合中//用来给下一行的元素所在的列作为排除条件判断columns.add(i);//把选中的单元格加入到,去除左对角线的集合中diagonals1.add(diagonal1);//把选中的单元格加入到,去除右对角线的集合中diagonals2.add(diagonal2);//递归遍历下一行,dfs(res,queens,n,row+1,columns,diagonals1,diagonals2);//剪枝操作queens[row] = -1;//将当前列和左对角线和右对角线的元素都删除,避免重复遍历columns.remove(i);diagonals1.remove(diagonal1);diagonals2.remove(diagonal2);}}}//转换格式public List<String> generateBoard(int[] queens,int n){//定义一个结果集,用于返回结果List<String> board = new ArrayList<>();//遍历所有行for(int i = 0; i < n; i++){char[] row = new char[n];Arrays.fill(row, '.');//将当前行所在的列的,位置置为Qrow[queens[i]] = 'Q';//将当前结果添加进结果集中board.add(new String(row));}return board;}
}

力扣HOT100 - 35. 搜索插入位置

 

解题思路:

二分法模板

class Solution {public int searchInsert(int[] nums, int target) {int left = 0;int right = nums.length - 1;while (left <= right) {int mid = left + ((right - left) >> 1);if (nums[mid] == target)return mid;else if (nums[mid] < target)left = mid + 1;elseright = mid - 1;}return left;}
}

力扣HOT100 - 74. 搜索二维矩阵

 

解题思路:

两次二分,第一次定位行,第二次定位列。

class Solution {public boolean searchMatrix(int[][] matrix, int target) {int m = matrix.length, n = matrix[0].length;int l = 0, r = m - 1;//定位行int row = -1;while (l <= r) {int mid = l + (r - l) / 2;if (matrix[mid][0] <= target && matrix[mid][n - 1] >= target) {row = mid;break;} else if (target < matrix[mid][0]) {r = mid - 1;} else {l = mid + 1;}}if (row == -1) return false;//定位列l = 0;r = n - 1;while (l <= r) {int mid = l + (r - l) / 2;//已知行row之后,就按照常规的二分来做if (target == matrix[row][mid])return true;else if (target < matrix[row][mid])r = mid - 1;elsel = mid + 1;}return false;}
}

力扣HOT100 - 34. 在排序数组中查找元素的第一个和最后一个位置

 

解题思路:

两次二分,第一次定左边的位置,第二次定右边的位置,也算模板。

class Solution {public int[] searchRange(int[] nums, int target) {int l = 0, r = nums.length - 1;int first = -1, last = -1;while (l <= r) {int mid = l + (r - l) / 2;if (nums[mid] == target) {first = mid;r = mid - 1;//重点,向左找} else if (nums[mid] > target) {r = mid - 1;} else {l = mid + 1;}}l = 0;r = nums.length - 1;while (l <= r) {int mid = l + (r - l) / 2;if (nums[mid] == target) {last = mid;l = mid + 1;//重点,向右找} else if (nums[mid] > target) {r = mid - 1;} else {l = mid + 1;}}return new int[] { first, last };}
}

力扣HOT100 - 33. 搜索旋转排序数组

 

解题思路:
旋转排序数组可分为N1 + N2两个部分,如:[4,5,6,7,1,2,3],N1为[4,5,6,7],N2为[1,2,3]
 必然满足以下两个条件:
 1. N1和N2都是分别递增的;
 2. N1中的所有元素大于N2中的所有元素;
以上两个条件可推出:nums[0]是N1中最小的数,即nums[0] > N2中的所有元素

 而mid不是在N1内就是在N2内
所以:如果nums[0] <= nums[mid],即mid落在了N1内,则[0, mid]肯定是有序的
       否则mid落在了N2内,则[mid, n)肯定是有序的

if (nums[0] <= nums[mid]) {
    // 左半边有序
} else {
    // 右半边有序
}

class Solution {public int search(int[] nums, int target) {int n = nums.length;if (n == 0) return -1;if (n == 1) return nums[0] == target ? 0 : -1;int l = 0, r = n - 1;while (l <= r) {int mid = l + (r - l) / 2;if (nums[mid] == target) {return mid;}if (nums[0] > nums[mid]) {if (nums[mid] < target && target <= nums[n - 1]) {l = mid + 1;} elser = mid - 1;} else {if (nums[0] <= target && target < nums[mid]) {r = mid - 1;} elsel = mid + 1;}}return -1;}
}

力扣HOT100 - 153. 寻找旋转排序数组中的最小值

 

解题思路:

与33题类似。

class Solution {public int findMin(int[] nums) {int l = 0;int r = nums.length - 1;if (nums[r] >= nums[l]) return nums[0];while (l <= r) {int mid = l + (r - l) / 2;if (nums[0] > nums[mid]) {r = mid - 1;} else {l = mid + 1;}}return nums[l];}
}

力扣HOT100 - 4. 寻找两个正序数组的中位数

 

解题思路:

两个数组合并,然后根据奇偶返回中位数。

class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int m = nums1.length;int n = nums2.length;int[] nums = new int[m + n];if (m == 0) {if (n % 2 == 0) return (nums2[n / 2 - 1] + nums2[n / 2]) / 2.0;else return nums2[n / 2];}if (n == 0) {if (m % 2 == 0) return (nums1[m / 2 - 1] + nums1[m / 2]) / 2.0;else return nums1[m / 2];}int cnt = 0;int i = 0, j = 0;while (cnt != (m + n)) {if (nums1[i] < nums2[j]) nums[cnt++] = nums1[i++];else nums[cnt++] = nums2[j++];if (i == m) {while (j != n)nums[cnt++] = nums2[j++];}if (j == n) {while (i != m)nums[cnt++] = nums1[i++];}}if (cnt % 2 == 0) return (nums[cnt / 2 - 1] + nums[cnt / 2]) / 2.0;else return nums[cnt / 2];}
}

力扣HOT100 - 20. 有效的括号

 

解题思路:

class Solution {private static final Map<Character,Character> map = new HashMap<Character,Character>(){{put('{','}'); put('[',']'); put('(',')'); put('?','?');}};public boolean isValid(String s) {if(s.length() > 0 && !map.containsKey(s.charAt(0))) return false;LinkedList<Character> stack = new LinkedList<Character>() {{ add('?'); }};for(Character c : s.toCharArray()){if(map.containsKey(c)) stack.addLast(c);else if(map.get(stack.removeLast()) != c) return false;}return stack.size() == 1;}
}

力扣HOT100 - 155. 最小栈

 

解题思路:

辅助栈

class MinStack {private Stack<Integer> stack;private Stack<Integer> min_stack;public MinStack() {stack = new Stack<>();min_stack = new Stack<>();}public void push(int val) {stack.push(val);if (min_stack.isEmpty() || val <= min_stack.peek())min_stack.push(val);}public void pop() {if (stack.pop().equals(min_stack.peek()))min_stack.pop();}public int top() {return stack.peek();}public int getMin() {return min_stack.peek();}
}

力扣HOT100 - 394. 字符串解码

 

解题思路:

辅助栈

class Solution {public String decodeString(String s) {int k = 0;StringBuilder res = new StringBuilder();Stack<Integer> kstack = new Stack<>();Stack<StringBuilder> restack = new Stack<>();for(char c : s.toCharArray()){if(c == '['){//碰到括号,记录K和当前res,归零。kstack.push(k);restack.push(res);k = 0;res = new StringBuilder(); }else if(c ==']'){//出最近的一个左括号入的k,当前res进行计算不入栈int curk = kstack.pop();StringBuilder temp = new StringBuilder();for(int i = 0; i < curk; i++){temp.append(res);}//与括号外合并res = restack.pop().append(temp);}else if(c >= '0' && c <= '9'){k = c - '0' + k * 10;//如果k是多位数需要x10}else{res.append(c);//如果是字母则缓慢添加}}return res.toString();}
}

力扣HOT100 - 739. 每日温度

 

解题思路:

单调栈

class Solution {public int[] dailyTemperatures(int[] temperatures) {int length = temperatures.length;int[] ans = new int[length];Deque<Integer> stack = new LinkedList<>();for (int i = 0; i < length; i++) {int temperature = temperatures[i];while (!stack.isEmpty() && temperature > temperatures[stack.peek()]) {int preIndex = stack.pop();ans[preIndex] = i - preIndex;}stack.push(i);}return ans;}
}

力扣HOT100 - 84. 柱状图中最大的矩形

解题思路:

单调栈

对于一个高度height[ i ],找左右两边均严格小于它的值。

class Solution {public int largestRectangleArea(int[] heights) {int n = heights.length;int[] left = new int[n];int[] right = new int[n];Deque<Integer> mono_stack = new ArrayDeque<>();for (int i = 0; i < n; i++) {while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {mono_stack.pop();}left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());mono_stack.push(i);}mono_stack.clear();for (int i = n - 1; i >= 0; i--) {while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {mono_stack.pop();}right[i] = (mono_stack.isEmpty() ? n : mono_stack.peek());mono_stack.push(i);}int ans = 0;for (int i = 0; i < n; i++) {ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);}return ans;}
}

力扣HOT100 - 215. 数组中第K个最大元素 

 

解题思路:

快速选择,目标是找出数组中第 k 小(或第 k 大)的元素,而不是对整个数组进行排序。

(需要和快排进行区分,快排的目的是排序)

注意:

i = l - 1, j = r + 1; 为什么要这么写?而不是 i = l; j = r ?

因为是先执行do语句的内容,一开始进循环就已经先i++或者j--了,所以进循环前需要-1和+1。

class Solution {public int findKthLargest(int[] nums, int k) {int n = nums.length;return quickselect(nums, 0, n - 1, n - k);}public int quickselect(int[] nums, int l, int r, int k) {if (l == r) return nums[k];int i = l - 1, j = r + 1;while (i < j) {do i++; while (nums[i] < nums[l]);do j--; while (nums[j] > nums[l]);if (i < j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}}if (k <= j) return quickselect(nums, l, j, k);else return quickselect(nums, j + 1, r, k);}
}

力扣HOT100 - 347. 前K个高频元素

 

解题思路:

小根堆(顺便练习一下优先队列)

class Solution {public int[] topKFrequent(int[] nums, int k) {Map<Integer, Integer> map = new HashMap<>();for (int num : nums) {map.put(num, map.getOrDefault(num, 0) + 1);}// int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {public int compare(int[] m, int[] n) {return m[1] - n[1];}});for (Map.Entry<Integer, Integer> entry : map.entrySet()) {int num = entry.getKey(), cnt = entry.getValue();if (queue.size() == k) {if (queue.peek()[1] < cnt) {queue.poll();queue.offer(new int[] { num, cnt });}} else {queue.offer(new int[] { num, cnt });}}int[] res = new int[k];for (int i = 0; i < k; i++) {res[i] = queue.poll()[0];}return res;}
}

力扣HOT100 - 295. 数据流的中位数

 

解题思路:

小顶堆 + 大顶堆

class MedianFinder {Queue<Integer> A, B;public MedianFinder() {A = new PriorityQueue<>();B = new PriorityQueue<>((x, y) -> (y - x));}public void addNum(int num) {if (A.size() != B.size()) {A.add(num);B.add(A.poll());} else {B.add(num);A.add(B.poll());}}public double findMedian() {return A.size() != B.size() ? A.peek() : (A.peek() + B.peek()) / 2.0;}
}

力扣HOT100 - 121. 买卖股票的最佳时机

 

解题思路:

每次遍历price,更新最小的cost和最大的profit

class Solution {public int maxProfit(int[] prices) {int cost = Integer.MAX_VALUE, profit = 0;for (int price : prices) {cost = Math.min(cost, price);profit = Math.max(profit, price - cost);}return profit;}
}

力扣HOT100 - 55. 跳跃游戏

 

解题思路:

class Solution {public boolean canJump(int[] nums) {int n = nums.length;int maxReach = 0;// 正常来说每次至少跳一格,所以最多循环n次for (int i = 0; i < n; i++) {if (i > maxReach) return false;// 这种情况代表遇到了0,跳不动了if (maxReach >= n - 1) return true;maxReach = Math.max(maxReach, i + nums[i]);}return false;}
}

力扣HOT100 - 45. 跳跃游戏 II

 

解题思路:

贪心

class Solution {public int jump(int[] nums) {int end = 0;int maxPosition = 0;int steps = 0;for (int i = 0; i < nums.length - 1; i++) {maxPosition = Math.max(maxPosition, i + nums[i]);if (i == end) {end = maxPosition;steps++;}}return steps;}
}

力扣HOT100 - 763. 划分字母区间

 

解题思路:

class Solution {public List<Integer> partitionLabels(String s) {int[] last = new int[26];int len = s.length();for (int i = 0; i < len; i++) {last[s.charAt(i) - 'a'] = i;//记录字母最远的下标}List<Integer> partition = new ArrayList<>();int start = 0, end = 0;for (int i = 0; i < len; i++) {end = Math.max(end, last[s.charAt(i) - 'a']);if (i == end) {partition.add(end - start + 1);start = end + 1;}}return partition;}
}

力扣HOT100 - 70. 爬楼梯

 

解题思路:

动态规划

注意 if 判断和 for 循环

class Solution {public int climbStairs(int n) {if (n <= 2) return n;int[] dp = new int[n + 1];dp[1] = 1;dp[2] = 2;for (int i = 3; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}

力扣HOT100 - 118. 杨辉三角

 

解题思路:

每个数字等于上一行的左右两个数字之和。

class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> res = new ArrayList<>();for (int i = 0; i < numRows; i++) {List<Integer> row = new ArrayList<>();for (int j = 0; j <= i; j++) {if (j == 0 || j == i) row.add(1);else row.add(res.get(i - 1).get(j - 1) + res.get(i - 1).get(j));}res.add(row);}return res;}
}

力扣HOT100 - 198. 打家劫舍

 

解题思路:

动态规划

class Solution {public int rob(int[] nums) {int len = nums.length;if (nums == null || len == 0) return 0;if (len == 1) return nums[0];int[] dp = new int[len];dp[0] = nums[0];dp[1] = Math.max(nums[0], nums[1]);for (int i = 2; i < len; i++) {dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);}return dp[len - 1];}
}

为什么不是int[] dp=new int[n+1];

下标从0开始就用new int[n]就行,如果从1开始会越界才会加1。

力扣HOT100 - 279. 完全平方数

 

解题思路:

动态规划

class Solution {public int numSquares(int n) {int[] dp = new int[n + 1];// 初始化dp数组,默认最坏情况是每个数都是由1相加得到的for (int i = 1; i <= n; i++) {dp[i] = i;}for (int i = 1; i <= n; i++) {for (int j = 1; j * j <= i; j++) {dp[i] = Math.min(dp[i], dp[i - j * j] + 1);}}return dp[n];}
}

力扣HOT100 - 322. 零钱兑换

 

解题思路:

动态规划

class Solution {public int coinChange(int[] coins, int amount) {int[] dp = new int[amount + 1];Arrays.fill(dp, amount + 1);dp[0] = 0;for (int i = 1; i <= amount; i++) {for (int j = 0; j < coins.length; j++) {if (coins[j] <= i) {dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);}}}return dp[amount] > amount ? -1 : dp[amount];}
}

力扣HOT100 - 139. 单词拆分

 

解题思路:

动态规划

class Solution {public boolean wordBreak(String s, List<String> wordDict) {Set<String> wordDictSet = new HashSet(wordDict);boolean[] dp = new boolean[s.length() + 1];dp[0] = true;for (int i = 1; i <= s.length(); i++) {for (int j = 0; j < i; j++) {if (dp[j] && wordDictSet.contains(s.substring(j, i))) {dp[i] = true;break;}}}return dp[s.length()];}
}

力扣HOT100 - 300. 最长递增子序列

 

解题思路:

动态规划

class Solution {public int lengthOfLIS(int[] nums) {if (nums.length == 0) return 0;int[] dp = new int[nums.length];int max = 0;Arrays.fill(dp, 1);for (int i = 0; i < nums.length; i++) {for (int j = 0; j < i; j++) {if (nums[j] < nums[i]) {dp[i] = Math.max(dp[i], dp[j] + 1);}}max = Math.max(max, dp[i]);}return max;}
}

力扣HOT100 - 152. 乘积最大子数组

 

解题思路:

方法一:暴力

class Solution {public int maxProduct(int[] nums) {int max = Integer.MIN_VALUE;int s = 1;for (int i = 0; i < nums.length; i++) {s = 1;for (int j = i ; j < nums.length; j++) {s *= nums[j];max = Math.max(max, s);}}return max;}
}

方法二:动态规划

class Solution {public int maxProduct(int[] nums) {int max = Integer.MIN_VALUE, imax = 1, imin = 1;for (int i = 0; i < nums.length; i++) {if (nums[i] < 0) {int tmp = imax;imax = imin;imin = tmp;}imax = Math.max(imax * nums[i], nums[i]);imin = Math.min(imin * nums[i], nums[i]);max = Math.max(max, imax);}return max;}
}

力扣HOT100 - 416. 分割等和子集

 

解题思路:

动态规划

对于当前考虑的元素 nums[i],如果 dp[ j - nums[ i ] ] 为 true,说明可以用前面的元素构成和为 j -nums[ i ] 的子集,那么在加上当前元素 nums[ i ] 的情况下,就可以构成和为 j 的子集,因此 dp[ j ] 更新为 true。如果 dp[ j - nums[ i ] ] 为 false,则说明无法使用前面的元素构成和为 j-nums[ i ] 的子集,那么无论如何也无法构成和为 j 的子集,因此 dp[ j ] 不变。

class Solution {public boolean canPartition(int[] nums) {int n = nums.length;if (n < 2) return false;int sum = 0, maxNum = 0;for (int num : nums) {sum += num;maxNum = Math.max(maxNum, num);}if (sum % 2 != 0) return false;int target = sum / 2;if (maxNum > target) return false;boolean[] dp = new boolean[target + 1];dp[0] = true;for (int i = 0; i < n; i++) {for (int j = target; j >= nums[i]; j--) {dp[j] = dp[j] || dp[j - nums[i]];}}return dp[target];}
}

力扣HOT100 - 32. 最长有效括号

 

解题思路:

class Solution {public int longestValidParentheses(String s) {int max = 0;// 也可以使用 Stack<Integer> stack=new Stack<>();但Stack是遗留类,不推荐Deque<Integer> stack = new LinkedList<>();stack.push(-1);for (int i = 0; i < s.length(); i++) {if (s.charAt(i) == '(') {stack.push(i);} else {stack.pop();if (stack.isEmpty()) stack.push(i);else max = Math.max(max, i - stack.peek());}}return max;}
}

力扣HOT100 - 62. 不同路径

 

解题思路:

动态规划

注意要初始化第一行和第一列的值

class Solution {public int uniquePaths(int m, int n) {int[][] dp = new int[m][n];for (int i = 0; i < m; i++) {dp[i][0] = 1;}for (int j = 0; j < n; j++) {dp[0][j] = 1;}for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m - 1][n - 1];}}

力扣HOT100 - 64. 最小路径和

 

解题思路:

动态规划

class Solution {public int minPathSum(int[][] grid) {int m = grid.length;int n = grid[0].length;if (grid == null || m == 0 || n == 0) return 0;int[][] dp = new int[m][n];dp[0][0] = grid[0][0];for (int i = 1; i < m; i++) {dp[i][0] = dp[i - 1][0] + grid[i][0];}for (int j = 1; j < n; j++) {dp[0][j] = dp[0][j - 1] + grid[0][j];}for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {dp[i][j] = Math.min(dp[i - 1][j] + grid[i][j], dp[i][j - 1] + grid[i][j]);}}return dp[m - 1][n - 1];}
}

力扣HOT100 - 5. 最长回文子串

 

解题思路:

动态规划

class Solution {public String longestPalindrome(String s) {// 特殊用例判断int len = s.length();if (len < 2) return s;int maxLen = 1;int begin = 0;// dp[i][j] 表示 s[i, j] 是否是回文串boolean[][] dp = new boolean[len][len];for (int i = 0; i < len; i++) {dp[i][i] = true;}for (int j = 1; j < len; j++) {for (int i = 0; i < j; i++) {if (s.charAt(i) != s.charAt(j)) dp[i][j] = false;else {if (j - i <= 2) dp[i][j] = true;else dp[i][j] = dp[i + 1][j - 1];//向内收,看里面的串是不是回文串}// 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,此时记录回文长度和起始位置if (dp[i][j] && j - i + 1 > maxLen) {maxLen = j - i + 1;begin = i;}}}return s.substring(begin, begin + maxLen);}
}

力扣HOT100 - 1143. 最长公共子序列

 

解题思路:

动态规划

class Solution {public int longestCommonSubsequence(String text1, String text2) {int m = text1.length(), n = text2.length();int[][] dp = new int[m + 1][n + 1];for (int i = 1; i <= m; i++) {char c1 = text1.charAt(i - 1);for (int j = 1; j <= n; j++) {char c2 = text2.charAt(j - 1);if (c1 == c2) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[m][n];}
}

力扣HOT100 - 72. 编辑距离

 

解题思路:

动态规划

class Solution {public int minDistance(String word1, String word2) {int n1 = word1.length();int n2 = word2.length();int[][] dp = new int[n1 + 1][n2 + 1];for (int j = 1; j <= n2; j++) dp[0][j] = dp[0][j - 1] + 1;for (int i = 1; i <= n1; i++) dp[i][0] = dp[i - 1][0] + 1;for (int i = 1; i <= n1; i++) {for (int j = 1; j <= n2; j++) {if (word1.charAt(i - 1) == word2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];else dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;}}return dp[n1][n2];}
}

力扣HOT100 - 136. 只出现一次的数字

 

解题思路:

class Solution {public int singleNumber(int[] nums) {int single = 0;for (int num : nums) {single ^= num;}return single;}
}

力扣HOT100 - 169. 多数元素

 

解题思路:

有点类似于Boyer-Moore 投票算法,但更加形象。

class Solution {public int majorityElement(int[] nums) {int winner = nums[0];int cnt = 1;for (int i = 1; i < nums.length; i++) {if (winner == nums[i]){cnt++;}                else if (cnt == 0) {winner = nums[i];cnt++;} else {cnt--;}}return winner;}
}

力扣HOT100 - 75. 颜色分类

 

解题思路:

单指针,对数组进行两次遍历。

class Solution {public void sortColors(int[] nums) {int p = 0;int n = nums.length;for (int i = 0; i < n; i++) {if (nums[i] == 0) {int tmp = nums[i];nums[i] = nums[p];nums[p] = tmp;p++;}}for (int i = p; i < n; i++) {if (nums[i] == 1) {int tmp = nums[i];nums[i] = nums[p];nums[p] = tmp;p++;}}}
}

力扣HOT100 - 31. 下一个排列

 

解题思路:

数字是逐步增大的

步骤如下:

class Solution {public void nextPermutation(int[] nums) {int i = nums.length - 2;while (i >= 0 && nums[i] >= nums[i + 1]) i--;if (i >= 0) {int j = nums.length - 1;while (j >= 0 && nums[i] >= nums[j]) j--;swap(nums, i, j);}reverse(nums, i + 1);}public void swap(int[] nums, int i, int j) {int tmp = nums[i];nums[i] = nums[j];nums[j] = tmp;}public void reverse(int[] nums, int start) {int left = start, right = nums.length - 1;while (left < right) {swap(nums, left, right);left++;right--;}}
}

力扣HOT100 - 287. 寻找重复数

 

解题思路:

快慢指针

  1. 第一步,慢指针每次移动一步,快指针每次移动两步,直到它们相遇。这一步保证了它们在环中相遇。

  2. 接下来,将其中一个指针(快指针或慢指针)重置到起点(即数组的第一个位置),然后两个指针都每次只移动一步。它们再次相遇的位置就是环的起始节点,也就是数组中重复的元素。

class Solution {public int findDuplicate(int[] nums) {int slow = 0, fast = 0;do {slow = nums[slow];fast = nums[nums[fast]];} while (slow != fast);slow = 0;while (slow != fast) {slow = nums[slow];fast = nums[fast];}return slow;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1559165.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统-系统调用

应用程序调用printf(),会触发系统调用write() 1、概念 操作系统服务的编程接口&#xff0c;通常由高级语言编写&#xff08;C/C&#xff09;&#xff0c;程序访问通常是通过高层次的API接口而不是直接进行系统调用。 2、三种最常用的应用程序编程接口&#xff08;API&#xf…

Vue深入了解

Vue深入了解 MVVMv-model (双向数据绑定原理)异步更新keep-alive原理$nextTick原理computed 和 watch 的区别css-scoped虚拟DOMVuex && PiniaVue-router原理proxy 与 Object.defineProperty组件通信方式 MVVM <!DOCTYPE html> <html lang"en">&…

AD原理图编译出现Net XX has no driving source

提示无驱动电压源&#xff0c;这是因为你的芯片管脚设置了电气属性造成的。 两种解决AD中出现Net has no driving source警告的方法。 方法一&#xff1a;取消电气属性检测&#xff0c;但不推荐&#xff1b; 打开原理图编译项&#xff0c;将NET no driving source 修改为no …

PostgreSQL的学习心得和知识总结(一百五十三)|[performance]将 OR 子句转换为 ANY 表达式

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

树控件QTreeWidget

树控件跟表格控件类似&#xff0c;也可以有多列&#xff0c;也可以只有1列&#xff0c;可以有多行&#xff0c;只不过每一行都是一个QTreeWidgetItem&#xff0c;每一行都是一个可以展开的树 常用属性和方法 显示和隐藏标题栏 树控件只有水平标题栏 //获取和设置标题栏的显…

PPT在线画SWOT分析图!这2个在线软件堪称办公必备!

swot分析ppt怎么做&#xff1f; swot分析是一个非常常用的战略分析框架&#xff0c;经常会在ppt中使用。想在ppt中绘制swot分析图&#xff0c;使用自带的形状工具可以制作出来&#xff0c;但绘制效率不够高&#xff0c;在需要大批量制作的场景下&#xff0c;会让人非常心累………

DepthB2R靶机打靶记录

一、靶机介绍 下载地址&#xff1a;https://download.vulnhub.com/depth/DepthB2R.ova 二、信息收集 根据靶机主页显示&#xff0c;确认靶机ip为192.168.242.132 端口扫描 nmap -p- -A 192.168.242.132 发现只开放了8080端口 用dirsearch扫个目录 apt-get update apt-get …

基于LORA的一主多从监测系统_0.96OLED

关联&#xff1a;0.96OLED hal硬件I2C LORA 在本项目中每个节点都使用oled来显示采集到的数据以及节点状态&#xff0c;OLED使用I2C接口与STM32连接&#xff0c;这个屏幕内部驱动IC为SSD1306&#xff0c;SSD1306作为从机地址为0x78 发送数据&#xff1a;起始…

【Linux】基本认知全套入门

目录 Linux简介 Linux发行版本 发行版选择建议 Centos-社区企业操作系统 Centos版本选择 Linux系统目录 Linux常用命令 SSH客户端 Linux文件操作命令 vim重要快捷键 应用下载与安装 netstat&#xff0c;ps与kill命令使用 Linux应用服务化 Linux用户与权限 Linu…

Telephony CarrierConfig配置

1、CarrierConfig配置介绍 CarrierConfig&#xff08;运营商配置&#xff09;&#xff0c;是Android为了针对不同运营商配置不同功能的配置文件&#xff0c;类似Modem的MBN配置&#xff0c;可以实现插入不同运营商卡&#xff0c;不同的功能实现或菜单显示等。 2、CarrierConfig…

力扣之1355.活动参与者

题目&#xff1a; Sql 测试用例&#xff1a; Create table If Not Exists Friends (id int, name varchar(30), activity varchar(30)); Create table If Not Exists Activities (id int, name varchar(30)); Truncate table Friends; insert into Friends (id, name, acti…

【数据结构与算法-高阶】并查集

【数据结构与算法-高阶】并查集 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;数据结构与算法&#x1f345; &#x1f33c;文章目录&#x1f33c; 1. 并查集原理 2. 并查集实现 3. 并查集应用 1. 并查集原理 在一些应用问题中&…

charAt,chartCodeAt,codePointAt,fromCodePoint,fromCharCode

生僻字的length算2,有些空格是特殊空格,比如\u3000 u3000不是全角空格&#xff0c;u3000是表意字空格&#xff08;Ideographic Space&#xff09;&#xff0c;宽度和一个表意字&#xff08;汉字&#xff09;相同。它应当被当做汉字来处理。比如&#xff0c;在一些排版中&#x…

OpenSource - License 开源项目 TrueLicense

文章目录 官网集成Demo 官网 https://truelicense.namespace.global/ https://github.com/christian-schlichtherle/truelicense 集成Demo https://github.com/christian-schlichtherle/truelicense-maven-archetype https://github.com/zifangsky/LicenseDemo https://git…

map和set(c++)

前言 在前面我们在介绍二叉搜索树时我们分别实现了一个key结构和key-val结构&#xff0c;如果我们再进一步完善这棵树&#xff0c;将二叉搜索树升级为红黑树去存储key和key-val那么我们就可以得到我们今天要介绍的主角map和set。当然了标准库的实现还是有很多需要注意的地方&a…

植物大战僵尸修改器-MFC

创建项目 创建mfc应用 基于对话框 打开资源视图下的 IDD_MFCAPPLICTION2_DIALOG 限制对话框大小 将属性中Border的值改为对话框外框 删除对话框中原有的控件 属性-外观-Caption 设置对话框标题 工具箱中拖放一个按钮 修改按钮名称 将按钮ID改为IDC_COURSE 在MFCApplication2…

k8s微服务

一 、什么是微服务 用控制器来完成集群的工作负载&#xff0c;那么应用如何暴漏出去&#xff1f;需要通过微服务暴漏出去后才能被访问 Service是一组提供相同服务的Pod对外开放的接口。 借助Service&#xff0c;应用可以实现服务发现和负载均衡。 service默认只支持4层负载均…

QT安装成功后-在创建项目时,发现仅有项目名文件

&#xff08;1&#xff09;QT安装成功后&#xff0c;发现仅有项目名文件其他可编辑文件缺失 &#xff08;2&#xff09;点击文件名左上角的感叹号显示【No kits are enabled for this project. Enable】 小编在尝试多次后发现&#xff0c;可以通过以下方式解决&#xff1a;QT软…

接着上一篇stp 实验继续

理论看上一篇&#xff0c;我们直接实验 首先找出&#xff52;&#xff4f;&#xff4f;&#xff54; 桥 很明显 &#xff53;&#xff57;&#xff11; 为&#xff52;&#xff4f;&#xff4f;&#xff54; 桥&#xff0c;所谓&#xff53;&#xff57;&#xff11;  &a…

从Hinton获得今年的诺贝尔物理学奖说起

“深度人工智能”是成都深度智谷科技旗下的人工智能教育机构订阅号&#xff0c;主要分享人工智能的基础知识、技术发展、学习经验等。此外&#xff0c;订阅号还为大家提供了人工智能的培训学习服务和人工智能证书的报考服务&#xff0c;欢迎大家前来咨询&#xff0c;实现自己的…