https://github.com/labuladong/fucking-algorithm
https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
- class Solution {
- public int removeDuplicates(int[] nums) {
- if(nums.length < 2){
- return nums.length;
- }
- // 定义快慢双指针
- int fast = 1;
- int slow = 0;
- while(fast < nums.length){
- if(nums[slow] != nums[fast]){
- slow++;
- nums[slow] = nums[fast];
- }
- fast++;
- }
- return slow + 1;
- }
- }
https://leetcode.cn/problems/remove-element/
- class Solution {
- public int removeElement(int[] nums, int val) {
- // 定义快慢双指针
- int fast = 0;
- int slow = 0;
- while (fast < nums.length) {
- if (nums[fast] != val) {
- nums[slow] = nums[fast];
- slow++;
- }
- fast++;
- }
- return slow;
- }
- }
https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/
- class Solution {
- public int[] twoSum(int[] numbers, int target) {
- // 定义对撞双指针
- int left = 0;
- int right = numbers.length - 1;
- while(left < right){
- if(numbers[left] + numbers[right] == target){
- return new int[] {left + 1, right + 1};
- }
- if(numbers[left] + numbers[right] < target){
- left++;
- }
- if(numbers[left] + numbers[right] > target){
- right--;
- }
- }
- return new int[]{-1, -1};
- }
- }
https://leetcode.cn/problems/reverse-string/
- class Solution {
- public void reverseString(char[] s) {
- // 定义对撞双指针
- int left = 0;
- int right = s.length - 1;
- char c;
- while(left < right){
- c = s[left];
- s[left] = s[right];
- s[right] = c;
- left++;
- right--;
- }
- }
- }
https://leetcode.cn/problems/longest-palindromic-substring/
- class Solution {
- /**
- * 主方法
- */
- public String longestPalindrome(String s) {
- String res = "";
- // 遍历字符串s
- for(int i = 0; i < s.length(); i++){
- String str1 = getPalindrome(s, i, i);
- String str2 = getPalindrome(s, i, i + 1);
- String str = str1.length() > str2.length() ? str1 : str2;
- res = str.length() > res.length() ? str : res;
- }
- return res;
- }
-
- /**
- * 获得以某两点为中心的最长子回文串
- */
- public String getPalindrome(String s, int left, int right){
- while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
- // 离心双指针
- left--;
- right++;
- }
- return s.substring(left + 1, right);
- }
- }
https://leetcode.cn/problems/merge-two-sorted-lists/
- class Solution {
- public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
- // 双指针list1、list2
- if(list1 == null){
- return list2;
- }
- if(list2 == null){
- return list1;
- }
- // 定义虚拟头结点
- ListNode dummy = new ListNode();
- ListNode current = dummy;
- // 推进
- while(list1 != null && list2 != null){
- if(list1.val <= list2.val){
- current.next = list1;
- list1 = list1.next;
- } else{
- current.next = list2;
- list2 = list2.next;
- }
- current = current.next;
- }
- // 处理剩余结点
- if(list1 != null){
- current.next = list1;
- }
- if(list2 != null){
- current.next = list2;
- }
- return dummy.next;
- }
- }
https://leetcode.cn/problems/partition-list/
- class Solution {
- public ListNode partition(ListNode head, int x) {
- if (head == null) {
- return head;
- }
- // 定义虚拟头结点
- ListNode dummy1 = new ListNode(-1, head);
- ListNode dummy2 = new ListNode(-1, head);
- // 定义双指针
- ListNode p1 = dummy1;
- ListNode p2 = dummy2;
- while(head != null){
- if(head.val < x){
- p1.next = head;
- p1 = head;
- p2.next = null;
- } else{
- p2.next = head;
- p2 = head;
- p1.next = null;
- }
- head = head.next;
- }
- // 连接两个链表
- p1.next = dummy2.next;
- return dummy1.next;
- }
- }
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
- class Solution {
- public ListNode removeNthFromEnd(ListNode head, int n) {
- // 定义虚拟头结点
- ListNode dummy = new ListNode(-1, head);
- // 定义双指针
- ListNode p1 = dummy;
- ListNode p2 = dummy;
- // p3是p2的前一个结点
- ListNode p3 = null;
- // p1先行
- for(int i = 0; i < n; i++){
- p1 = p1.next;
- }
- // p1、p2、p3同时推进
- while(p1 != null){
- if(p3 == null){
- p3 = p2;
- } else{
- p3 = p3.next;
- }
- p1 = p1.next;
- p2 = p2.next;
- }
- // 删除p2结点
- p3.next = p2.next;
- return dummy.next;
- }
- }
https://leetcode.cn/problems/middle-of-the-linked-list/
- class Solution {
- public ListNode middleNode(ListNode head) {
- // 定义虚拟头结点
- ListNode dummy = new ListNode(-1, head);
- // 定义快慢双指针
- ListNode p1 = dummy;
- ListNode p2 = dummy;
- while(p1 != null){
- p1 = p1.next;
- p2 = p2.next;
- if(p1 == null || p1.next == null){
- return p2;
- }
- p1 = p1.next;
- }
- return null;
- }
- }
https://leetcode.cn/problems/linked-list-cycle/
- class Solution {
- public boolean hasCycle(ListNode head) {
- if(head == null || head.next == null){
- return false;
- }
- // 定义快慢双指针
- ListNode p1 = head;
- ListNode p2 = head;
- while(p1 != null && p1.next != null){
- p1 = p1.next.next;
- p2 = p2.next;
- if(p1 == p2){
- return true;
- }
- }
- return false;
- }
- }
https://leetcode.cn/problems/intersection-of-two-linked-lists/
- class Solution {
- public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
- // 定义双指针
- ListNode p1 = headA;
- ListNode 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;
- }
- }
https://leetcode.cn/problems/reverse-linked-list/
- class Solution {
- public ListNode reverseList(ListNode head) {
- // base case
- if(head == null || head.next == null){
- return head;
- }
- // 前序位置(无操作)
- // 递归
- ListNode last = reverseList(head.next);
- // 后序位置
- head.next.next = head;
- head.next = null;
- return last;
- }
- }
https://leetcode.cn/problems/reverse-linked-list-ii/
- class Solution {
- ListNode mark = null;
-
- /**
- * 主方法
- */
- public ListNode reverseBetween(ListNode head, int left, int right) {
- if (left == 1) {
- return reverseN(head, right);
- }
- head.next = reverseBetween(head.next, left - 1, right - 1);
- return head;
- }
-
- /**
- * 反转链表的前n个结点
- */
- ListNode reverseN(ListNode head, int n) {
- if (n == 1) {
- mark = head.next;
- return head;
- }
- ListNode last = reverseN(head.next, n - 1);
- head.next.next = head;
- head.next = mark;
- return last;
- }
- }
https://leetcode.cn/problems/palindrome-linked-list/
- class Solution {
- ListNode left;
-
- /**
- * 主方法
- */
- public boolean isPalindrome(ListNode head) {
- left = head;
- return work(left);
- }
-
- /**
- * 判断是否是回文链表
- */
- public boolean work(ListNode current){
- if(current == null){
- return true;
- }
- boolean res = work(current.next);
- res = res && (left.val == current.val);
- left = left.next;
- return res;
- }
- }
- // 滑动窗口算法框架
- void slidingWindow(string s) {
- unordered_map<char, int> window;
-
- int left = 0, right = 0;
- while (right < s.size()) {
- // c是将移入窗口的字符
- char c = s[right];
- // 增大窗口
- right++;
- // 进行窗口内数据的一系列更新
- ...
-
- /*** debug 输出的位置 ***/
- printf("window: [%d, %d)\n", left, right);
- /********************/
-
- // 判断左侧窗口是否要收缩
- while (window needs shrink) {
- // d 是将移出窗口的字符
- char d = s[left];
- // 缩小窗口
- left++;
- // 进行窗口内数据的一系列更新
- ...
- }
- }
- }
https://leetcode.cn/problems/minimum-window-substring/
- class Solution {
- public String minWindow(String s, String t) {
- // 字符串转数组
- char[] sArr = s.toCharArray();
- char[] tArr = t.toCharArray();
- // 子串
- Map
need = new HashMap(); - for(char c : tArr){
- need.put(c, need.getOrDefault(c, 0) + 1);
- }
- // 窗口
- Map
window = new HashMap(); - int left = 0;
- int right = 0;
- // 匹配度
- int valid = 0;
- // 记录结果
- int start = 0;
- int len = Integer.MAX_VALUE;
- // 窗口滑动
- while(right < sArr.length){
- // 右指针前进, 扩大窗口
- char c = sArr[right];
- right++;
- if(need.containsKey(c)){
- window.put(c, window.getOrDefault(c, 0) + 1);
- if(window.getOrDefault(c, 0).equals(need.getOrDefault(c, 0))){
- valid++;
- }
- }
- // 窗口完全覆盖子串
- while(valid == need.size()){
- // 记录当前窗口
- if(right - left < len){
- start = left;
- len = right - left;
- }
- // 左指针前进, 缩小窗口
- char d = sArr[left];
- left++;
- if(need.containsKey(d)){
- if(window.getOrDefault(d, 0).equals(need.getOrDefault(d, 0))){
- valid--;
- }
- window.put(d, window.getOrDefault(d, 0) - 1);
- }
- }
- }
- return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
- }
- }
https://leetcode.cn/problems/permutation-in-string/
- class Solution {
- public boolean checkInclusion(String s1, String s2) {
- // 字符串转数组
- char[] s1Arr = s1.toCharArray();
- char[] s2Arr = s2.toCharArray();
- // 子串
- Map
need = new HashMap(); - for(char c : s1Arr){
- need.put(c, need.getOrDefault(c, 0) + 1);
- }
- // 窗口
- Map
window = new HashMap(); - int left = 0;
- int right = 0;
- // 匹配度
- int valid = 0;
- // 窗口滑动
- while(right < s2Arr.length){
- // 右指针前进, 扩大窗口
- char c = s2Arr[right];
- right++;
- if(need.containsKey(c)){
- window.put(c, window.getOrDefault(c, 0) + 1);
- if(window.getOrDefault(c, 0) <= need.getOrDefault(c, 0)){
- valid++;
- }
- }
- // 窗口大小不能超过s1的长度
- while(right - left >= s1Arr.length){
- // 匹配成功
- if(valid == s1Arr.length){
- return true;
- }
- // 左指针前进, 缩小窗口
- char d = s2Arr[left];
- left++;
- if(need.containsKey(d)){
- if(window.getOrDefault(d, 0) <= need.getOrDefault(d, 0)){
- valid--;
- }
- window.put(d, window.getOrDefault(d, 0) - 1);
- }
- }
- }
- return false;
- }
- }
https://leetcode.cn/problems/find-all-anagrams-in-a-string/
- class Solution {
- public List
findAnagrams(String s, String p) { - // 字符串转数组
- char[] sArr = s.toCharArray();
- char[] pArr = p.toCharArray();
- // 子串
- Map
need = new HashMap(); - for(char c : pArr){
- need.put(c, need.getOrDefault(c, 0) + 1);
- }
- // 窗口
- Map
window = new HashMap(); - int left = 0;
- int right = 0;
- // 匹配度
- int valid = 0;
- // 记录结果
- List
res = new ArrayList(); - // 窗口滑动
- while(right < sArr.length){
- // 右指针前进, 扩大窗口
- char c = sArr[right];
- right++;
- if(need.containsKey(c)){
- window.put(c, window.getOrDefault(c, 0) + 1);
- if(window.getOrDefault(c, 0) <= need.getOrDefault(c, 0)){
- valid++;
- }
- }
- // 窗口大小不能超过p的长度
- while(right - left >= pArr.length){
- // 匹配成功
- if(valid == pArr.length){
- res.add(left);
- }
- // 左指针前进, 缩小窗口
- char d = sArr[left];
- left++;
- if(need.containsKey(d)){
- if(window.getOrDefault(d, 0) <= need.getOrDefault(d, 0)){
- valid--;
- }
- window.put(d, window.getOrDefault(d, 0) - 1);
- }
- }
- }
- return res;
- }
- }
https://leetcode.cn/problems/longest-substring-without-repeating-characters/
- class Solution {
- public int lengthOfLongestSubstring(String s) {
- // 字符串转数组
- char[] sArr = s.toCharArray();
- // 窗口
- Map
window = new HashMap(); - int left = 0;
- int right = 0;
- // 记录结果
- int len = 0;
- // 窗口滑动
- while(right < sArr.length){
- // 右指针前进, 扩大窗口
- char c = sArr[right];
- right++;
- window.put(c, window.getOrDefault(c, 0) + 1);
- // 窗口中不能包含重复元素
- while(window.getOrDefault(c, 0) > 1){
- // 左指针前进, 缩小窗口
- char d = sArr[left];
- left++;
- window.put(d, window.getOrDefault(d, 0) - 1);
- }
- // 更新结果
- if(right - left > len){
- len = right - left;
- }
- }
- return len;
- }
- }
https://leetcode.cn/problems/repeated-dna-sequences/
- class Solution {
- public List
findRepeatedDnaSequences(String s) { - // 字符串转数组
- char[] sArr = s.toCharArray();
- // char数组转int数组
- int[] nums = new int[sArr.length];
- for(int i = 0; i < nums.length; i++){
- switch(sArr[i]){
- case 'A':
- nums[i] = 0;
- break;
- case 'G':
- nums[i] = 1;
- break;
- case 'C':
- nums[i] = 2;
- break;
- case 'T':
- nums[i] = 3;
- break;
- }
- }
- // 窗口位数、进制、最高位代表的值
- int L = 10;
- int R = 4;
- int RL = (int) Math.pow(R, L - 1);
- // 窗口hash
- int windowHash = 0;
- // 记录结果
- Set
seen = new HashSet(); - Set
res = new HashSet(); - // 窗口滑动
- int left = 0;
- int right = 0;
- while(right < nums.length){
- // 计算窗口hash
- windowHash = windowHash * R + nums[right];
- right++;
- // 窗口大小为定值L
- if(right - left == L){
- if(seen.contains(windowHash)){
- res.add(s.substring(left, right));
- } else{
- seen.add(windowHash);
- }
- windowHash = windowHash - nums[left] * RL;
- left++;
- }
- }
- return new LinkedList(res);
- }
- }
- int binarySearch(int[] nums, int target) {
- int left = 0, right = ...;
-
- while(...) {
- int mid = left + (right - left) / 2;
- if (nums[mid] == target) {
- ...
- } else if (nums[mid] < target) {
- left = ...
- } else if (nums[mid] > target) {
- right = ...
- }
- }
- return ...;
- }
如图,target=5的情况下,搜索左侧边界得到的值为6,搜索右侧边界得到的值为4。
https://leetcode.cn/problems/binary-search/
- class Solution {
- public int search(int[] nums, int target) {
- int left = 0;
- int right = nums.length - 1;
- // 二分查找
- while(left <= right){
- int mid = left + (right - left) / 2;
- if(nums[mid] == target){
- return mid;
- } else if(nums[mid] > target){
- right = mid - 1;
- } else if(nums[left] < target){
- left = mid + 1;
- }
- }
- return -1;
- }
- }
https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/
- class Solution {
- public int[] searchRange(int[] nums, int target) {
- if(nums.length == 0){
- return new int[]{-1, -1};
- }
- // 查找范围: [0, nums.length - 1]
- int left = 0;
- int right = nums.length - 1;
- // 终止条件: left == right + 1
- while(left <= right){
- int mid = left + (right - left) / 2;
- if(nums[mid] == target){
- right = mid - 1;
- } else if(nums[mid] > target){
- right = mid - 1;
- } else if(nums[mid] < target){
- left = mid + 1;
- }
- }
- int pl = (left != nums.length && nums[left] == target) ? left : -1;
- left = 0;
- right = nums.length - 1;
- while(left <= right){
- int mid = left + (right - left) / 2;
- if(nums[mid] == target){
- left = mid + 1;
- } else if(nums[mid] > target){
- right = mid - 1;
- } else if(nums[mid] < target){
- left = mid + 1;
- }
- }
- int pr = (right != -1 && nums[right] == target) ? right : -1;
- return new int[]{pl, pr};
- }
- }
力扣875 爱吃香蕉的珂珂
https://leetcode.cn/problems/koko-eating-bananas/
力扣1011 在D天内送达包裹的能力
https://leetcode.cn/problems/capacity-to-ship-packages-within-d-days/
力扣410 分割数组的最大值
https://leetcode.cn/problems/split-array-largest-sum/
https://leetcode.cn/problems/range-sum-query-immutable/
- class NumArray {
- private int[] preNums;
-
- /**
- * 构造方法
- */
- public NumArray(int[] nums) {
- preNums = new int[nums.length + 1];
- preNums[0] = 0;
- // 构建前缀和数组
- for(int i = 1; i < preNums.length; i++){
- preNums[i] = preNums[i - 1] + nums[i - 1];
- }
- }
-
- /**
- * 获取区域内元素总和
- */
- public int sumRange(int left, int right) {
- return preNums[right + 1] - preNums[left];
- }
- }
https://leetcode.cn/problems/range-sum-query-2d-immutable/
- class NumMatrix {
- private int[][] preSum;
-
- /**
- * 构造方法
- */
- public NumMatrix(int[][] matrix) {
- int m = matrix.length;
- int n = matrix[0].length;
- // 构建二维前缀和数组
- preSum = new int[m + 1][n + 1];
- for(int i = 1; i <= m; i++){
- for(int j = 1; j <= n; j++){
- preSum[i][j] = matrix[i - 1][j - 1] + preSum[i - 1][j] + preSum[i][j - 1] - preSum[i - 1][j - 1];
- }
- }
- }
-
- /**
- * 获取子矩阵元素总和
- */
- public int sumRegion(int row1, int col1, int row2, int col2) {
- return preSum[row2 + 1][col2 + 1] - preSum[row1][col2 + 1] - preSum[row2 + 1][col1] + preSum[row1][col1];
- }
- }
https://leetcode.cn/problems/random-pick-with-weight/
- class Solution {
- private int[] preSums;
- private Random rand = new Random();
-
- /**
- * 构造方法
- */
- public Solution(int[] w) {
- // 定义前缀和数组
- preSums = new int[w.length + 1];
- preSums[0] = 0;
- for(int i = 1; i < preSums.length; i++){
- preSums[i] = preSums[i - 1] + w[i - 1];
- }
- }
-
- /**
- * 按权重随机选择
- */
- public int pickIndex() {
- // 随机数生成范围: [1, preSums[preSums.length - 1]]
- int target = rand.nextInt(preSums[preSums.length - 1]) + 1;
- int left = 0;
- int right = preSums.length - 1;
- // 二分查找 左边界
- while(left <= right){
- int mid = left + (right - left) / 2;
- if(preSums[mid] == target){
- right = mid - 1;
- } else if(preSums[mid] > target){
- right = mid - 1;
- } else if(preSums[mid] < target){
- left = mid + 1;
- }
- }
- return left - 1;
- }
- }
https://leetcode.cn/problems/corporate-flight-bookings/
- class Solution {
- public int[] corpFlightBookings(int[][] bookings, int n) {
- int[] diff = new int[n + 1];
- int a;
- int b;
- int c;
- // 构建差分数组
- for(int i = 0; i < bookings.length; i++){
- a = bookings[i][0];
- b = bookings[i][1];
- c = bookings[i][2];
- diff[a - 1] += c;
- diff[b] -= c;
- }
- int[] res = new int[n];
- // 根据差分数组反推结果
- res[0] = diff[0];
- for(int j = 1; j < n; j++){
- res[j] = res[j - 1] + diff[j];
- }
- return res;
- }
- }
https://leetcode.cn/problems/car-pooling/
- class Solution {
- public boolean carPooling(int[][] trips, int capacity) {
- // 0到1000共1001
- int[] diff = new int[1001];
- int a,b,c;
- // 构建差分数组
- for(int i = 0; i < trips.length; i++){
- a = trips[i][0];
- b = trips[i][1];
- c = trips[i][2];
- diff[b] += a;
- diff[c] -= a;
- }
- int[] res = new int[1001];
- // 根据差分数组反推结果
- res[0] = diff[0];
- if(res[0] > capacity){
- return false;
- }
- for(int j = 1; j < 1001; j++){
- res[j] = res[j - 1] + diff[j];
- if(res[j] > capacity){
- return false;
- }
- }
- return true;
- }
- }