查询修改O(1) 增删O(n)

image.png


3. 求三数之和

image.png

先排序 然后循环一遍

除了第一遍以外 调过重复的元素 然后双指针向内夹逼

  1. class Solution {
  2. public List<List<Integer>> threeSum(int[] nums) {
  3. Arrays.sort(nums);
  4. List<List<Integer>> res = new ArrayList<>();
  5. for (int i = 0; i < nums.length - 2; i++) {
  6. if (i == 0 || (i > 0 && nums[i] != nums[i - 1] && nums[i] <= 0)) {
  7. int lo = i + 1, hi = nums.length -1, sum = 0 - nums[i];
  8. while (lo < hi) {
  9. if (nums[lo] + nums[hi] == sum) {
  10. res.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
  11. while (lo < hi && nums[lo] == nums[lo + 1]) lo++;
  12. while (lo < hi && nums[hi] == nums[hi - 1]) hi--;
  13. lo++; hi--;
  14. } else if (nums[lo] + nums[hi] < sum) {
  15. lo++;
  16. } else {
  17. hi--;
  18. }
  19. }
  20. }
  21. }
  22. return res;
  23. }
  24. }

7. 爬楼梯

image.png

  1. // 1:1
  2. // 2: 2
  3. // 3: 3
  4. // 4:5
  5. // f(n) = f(n-1) + f(n-2)
  6. class Solution {
  7. public int climbStairs(int n) {
  8. if (n < 3) return n;
  9. int x1 = 1;
  10. int x2 = 2;
  11. int x3 = 3;
  12. for (int i = 0; i < n - 3; i++) {
  13. x3 = x2 + x3;
  14. x1 = x2;
  15. x2 = x3 - x2;
  16. }
  17. return x3;
  18. }
  19. }

11. 盛水最多的容器

image.png
image.png

  1. // 1.暴力求解 两次选好 并记录最高的 会超时
  2. // 2.双指针 左右夹逼
  3. class Solution {
  4. public int maxArea(int[] height) {
  5. int max = 0;
  6. //双指针往中间夹逼
  7. for (int i = 0, j = height.length - 1; i != j; ) {
  8. int area = (j - i) * Math.min(height[i], height[j]);
  9. max = max > area ? max : area;
  10. //谁矮谁往前走
  11. if (height[i] < height[j]) {
  12. i++;
  13. } else {
  14. j--;
  15. }
  16. }
  17. return max;
  18. }
  19. }

66. 加一

image.png

  1. class Solution {
  2. public int[] plusOne(int[] digits) {
  3. for (int i = digits.length -1; i >= 0; i--) {
  4. if (digits[i] < 9) {
  5. digits[i]++;
  6. return digits;
  7. }
  8. digits[i] = 0;
  9. }
  10. int[] res = new int[digits.length + 1];
  11. res[0] = 1;
  12. return res;
  13. }
  14. }

88. 合并两个有序数组

image.png

  1. class Solution {
  2. public void merge(int[] nums1, int m, int[] nums2, int n) {
  3. int i = m + n - 1;
  4. int j = m - 1;
  5. int k = n - 1;
  6. while (j >= 0 && k >= 0) {
  7. if (nums1[j] > nums2[k]) {
  8. nums1[i--] = nums1[j--];
  9. } else {
  10. nums1[i--] = nums2[k--];
  11. }
  12. }
  13. while (k >= 0) {
  14. nums1[i--] = nums2[k--];
  15. }
  16. }
  17. }

189. 选择数组

image.png

  1. class Solution {
  2. public void rotate(int[] nums, int k) {
  3. k %= nums.length;
  4. reverse(nums, 0, nums.length - 1);
  5. reverse(nums, 0, k - 1);
  6. reverse(nums, k, nums.length -1);
  7. }
  8. public void reverse(int[] nums, int start, int end) {
  9. while (start < end) {
  10. int tmp = nums[start];
  11. nums[start] = nums[end];
  12. nums[end] = tmp;
  13. start++;
  14. end--;
  15. }
  16. }
  17. }

283. 零移动

image.png

  1. // 1. 新数组 最优解 但是题目禁止 O(n)
  2. // 2. 循环一次 把大于0的往前挪 最后补领 O(n)
  3. // 3. 双指针 一个指向下一个等于0的数 另一个指向第一个指针下一个不等于0的数 不断循环 直到超出界限
  4. //第二种解法
  5. class Solution {
  6. public void moveZeroes(int[] nums) {
  7. int insertPos = 0;
  8. for (int num : nums) {
  9. if (num != 0) nums[insertPos++] = num;
  10. }
  11. while (insertPos < nums.length) {
  12. nums[insertPos++] = 0;
  13. }
  14. }
  15. }
  1. // 1. 新数组 最优解 但是题目禁止 O(n)
  2. // 2. 循环一次 把大于0的往前挪 最后补领 O(n)
  3. // 3. 双指针 一个指向下一个等于0的数 另一个指向第一个指针下一个不等于0的数 不断循环 直到超出界限
  4. // 第三种解法
  5. class Solution {
  6. public void moveZeroes(int[] nums) {
  7. int left = 0;
  8. int right = 0;
  9. int len = nums.length;
  10. while (true) {
  11. while (left < len && nums[left] != 0) left++;
  12. right = left + 1;
  13. while (right < len && nums[right] == 0) right++;
  14. if (left == len || right == len) break;
  15. int tmp = nums[left];
  16. nums[left] = nums[right];
  17. nums[right] = tmp;
  18. }
  19. }
  20. }