4寻找两个有序数组的中位数

思路:

  • 其中一个为空的情况,利用len/2和(len-1)/2两个结果来求中位数
  • 两者不为空,调用helper
    • 当其中一个被筛选完,就选另一个的left + k
    • 当两个数组都还有候选数字,而k减到0时,取两个数组中的left最小者
    • k未到0时,分别从两者中取(k-1)/2。(考虑取第10时,相当于取第9(0开始),则9/2和(9-1)/2都是4,即取0~4共5个。取前11时,同样应该取5个,但11/2等于5,就是取6个了)当然,取值不能超过边界right。
    • 判断两数组的取值中最大的哪个小,那么该组小的那部分就可以在下次调用时忽略了。新的边界要+1做调整。
  1. int m = arr1.length;
  2. int n = arr2.length;
  3. if (m == 0) return (arr2[(n - 1) / 2] + arr2[(n / 2)]) / 2.0;
  4. if (n == 0) return (arr1[(m - 1) / 2] + arr1[(m / 2)]) / 2.0;
  5. int res1 = helper(arr1, 0, m - 1, arr2, 0, n - 1, (m + n -1) / 2);
  6. int res2 = helper(arr1, 0, m - 1, arr2, 0, n - 1, (m + n) / 2);
  7. return (res1 + res2) / 2.0;
  8. // helper
  9. if (left1 > right1) return arr2[left2 + k];
  10. if (left2 > right2) return arr1[left1 + k];
  11. if (k == 0) return Math.min(arr1[left1], arr2[left2]);
  12. int newLeft1 = Math.min(left1 + (k - 1) / 2, right1); // 参考上面,这里也是-1
  13. int newLeft2 = Math.min(left2 + (k - 1) / 2, right2);
  14. if (arr1[newLeft1] < arr2[newLeft2]) {
  15. return helper(arr1, newLeft1 + 1, right1, arr2, left2, right2, k - newLeft1 - 1 + left1);
  16. } else {
  17. return helper(arr1, left1, right1, arr2, newLeft2 + 1, right2, k - newLeft2 - 1 + left2);

11盛最多水的容器,42接雨水

11盛最多水的容器

思路:

  • 设置左右指针
  • 循环,只要left<right
    • 计算当前最大装水量,然后较低的边界收缩。
  1. while (left < right){
  2. int lh = height[left], rh = height[right];
  3. res = Math.max(res, Math.min(lh, rh) * (right - left));
  4. if (lh < rh) left++;
  5. else right--;
  6. }

42接雨水

思路:

  • 循环

    • 计算当前最低位并移动最低位的指针
    • 根据当前最低位以及过去level的最高位来确定level。(实际上level从0开始,说明level是通过lower来提高的,只要曾经出现过高的边界,那么level就不需要降低,因为已经有足够高的边界来容纳这个level)
    • res累加上当前最低位与水位的差
  1. while (right > left){
  2. // 计算当前最低位并移动最低位的指针
  3. int lower = height[(height[left] < height[right]) ? left++ : right--];
  4. // 根据目前两个指针各自所遇到最高值中较小的那个值来更新可以装载的水位
  5. // 就是木桶原理,短板决定水位,当短板高于旧水位、或者说是短板高于旧短板,水位就提高了
  6. level = Math.max(lower, level);
  7. // 根据当前指针的高度以及水位的差值计算该坐标下的雨水量
  8. res += level - lower;
  9. }

15三数之和,16最接近的三数之和,18四数之和

三数之和

思路:

  • 排序,用来考虑可能性、后面去重和mid与right的调整

  • 遍历

    • 以当前数作为left,并去重

    • 以left+1为mid,len-1为right,计算mid和right值的和,比较与left的差距,调整mid和right的位置。如果和等于left,记录left、mid和right,并调整mid和right,同时去重。

  1. Arrays.sort(nums);
  2. List<List<Integer>> res = new ArrayList<>();
  3. int n = nums.length;
  4. // 可能性,注意n == 0
  5. if (n == 0 || nums[0] > 0 || nums[n-1] < 0) return res;
  6. // 遍历
  7. for (int left = 0; left < n - 2 && nums[left] <= 0; left++){
  8. // left去重
  9. if (left != 0 && nums[left] == nums[left - 1]) continue;
  10. // mid、right、target变量
  11. int mid = left + 1, right = n - 1, target = -nums[left];
  12. // 遍历mid到right
  13. while (mid < right){
  14. // 大于
  15. if (nums[mid] + nums[right] > target) right--;
  16. // 小于
  17. else if (nums[mid] + nums[right] < target) mid++;
  18. // 相等,去重
  19. else {
  20. res.add(Arrays.asList(nums[left], nums[mid], nums[right]));
  21. mid++;
  22. right--;
  23. while(mid<right && nums[mid] == nums[mid-1]) mid++;
  24. while(mid<right && nums[right] == nums[right+1]) right--;
  25. }
  26. }
  27. }
  28. return res;
  29. // 四数和
  30. for (int i = 0; i < n - 3 && nums[i]*4 <= target; i++){
  31. if (i > 0 && nums[i] == nums[i-1]) continue;
  32. if(nums[i] + 3*nums[n-1] < target) continue;
  33. for (int j = i + 1; j < n - 2 && nums[i] + nums[j]*3 <= target ; j++){
  34. if (j > i + 1 && nums[j] == nums[j-1]) continue;

最接近的三数之和

思路:

  • 设置closest和diff并初始化。(由于找最接近,所以只要有三个数就是必定存在的)
  • 与上面类似,需要遍历(可以不考虑mid和right的去重,省事)
    • 遍历开始就是判断新的和是否需要更新diff和closet,然后根据和于target的差距调整right和mid(加上sum==target的判断会快一点)
  1. Arrays.sort(nums);
  2. int n = nums.length;
  3. int closest = nums[0] + nums[n/2] + nums[n-1];
  4. int diff = Math.abs(target - closest);
  5. for (int left = 0; left < n-2; left++){
  6. if (left != 0 && nums[left] == nums[left-1]) continue;
  7. int mid = left +1, right = n - 1;
  8. while (mid < right){
  9. int sum = nums[left] + nums[mid] + nums[right];
  10. int newDiff = Math.abs(target - sum);
  11. if (newDiff < diff){
  12. diff = newDiff;
  13. closest = sum;
  14. }
  15. if (sum > target) right--;
  16. else if(sum < target) mid++;
  17. else return target;
  18. }
  19. }

26/80删除排序数组中的重复项, 27移除元素

思路:

  • 设置去重指针
  • 遍历,从1开始
    • 如果当前数与去重指针不同,去重指针的下一个就可改写为当前数的值
  • 返回去重指针+1
  1. int n = nums.length;
  2. if (n <= 1) return n;
  3. int p = 0; // 如果允许重复k次,p = k-1
  4. for (int i = 1; i< n; i++){ // 如果允许重复k次,则从k开始
  5. // 如果允许重复k次,则为num[p-k+1]
  6. if (nums[p] != nums[i]) nums[++p] = nums[i];
  7. }
  8. return p + 1;

27移除元素

参考list中的移除元素,由于不确定第一个是否需要去除,所以去重指针定义为-1。其他近乎于上面一样。只不过比较的是nums[i] 与 val,而上面是num[p] 与nums[i]

  1. int p = -1;
  2. for(int num : nums){
  3. if (num != val) nums[++p] = num;
  4. }
  5. return p + 1;

31下一个排列

思路:

  • 从右往左,找出第一个小于右边的数字的index x
  • 判断是否存在这个数a,如果存在,要对它进行一次交换
    • 再次从右往左找第一个小于大于a的数字的index,将两个数位置交换
  • reverse从index x到末尾的数字
  1. public void nextPermutation(int[] nums) {
  2. int n = nums.length, i = n - 2, j = n - 1;
  3. while (i >= 0 && nums[i] >= nums[i + 1]) --i;
  4. if (i > -1) {
  5. while (nums[j] <= nums[i]) --j;
  6. swap(nums, i, j);
  7. }
  8. reverse(nums, i+1, n-1);
  9. }
  10. private static void reverse(int[] nums, int startIndex, int endIndex) {
  11. while (startIndex < endIndex) {
  12. swap(nums, startIndex++, endIndex--);
  13. }
  14. }

53最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

  1. 输入: [-2,1,-3,4,-1,2,1,-5,4],
  2. 输出: 6
  3. 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6

思路:

  • 设置res = Integer.MIN_VALUE(它是根据curSum取的)和curSum = 0 (由上述“子数组最少包含一个元素”,可以将curSum和res设为mums[0],并从1开始遍历,参考下面分治法的代码)
  • 遍历
  1. // curSum的思想是,如果当前值加上之前的累加值反而变少了,
  2. // 那么说明之前的子序列已经比不上现在的一个数了,可以重新开始累加了。
  3. curSum = Math.max(curSum + num, num);
  4. res = Math.max(res, curSum);
  1. // 分治法
  2. public int maxSubArray(int[] nums) {
  3. return helper(nums, 0, nums.length - 1);
  4. }
  5. public int helper(int[] nums, int left, int right) {
  6. // 底层返回
  7. // 返回left的原因是,mid是通过除法得到的,结果有可能等于left,然后调用时mid - 1就有可能得-1
  8. // 例如 0 和 1, 9 和 10,前者mid = 0,后者 9,在调用时,只有mid-1会超出范围
  9. if (left >= right) return nums[left];
  10. // 找中间点,对左半边和右半边递归调用
  11. int mid = left + (right - left) / 2;
  12. int lmax = helper(nums, left, mid - 1);
  13. int rmax = helper(nums, mid + 1, right);
  14. int mmax = nums[left], msum = mmax;
  15. for (int i = left + 1; i <= right; i++){
  16. msum = Math.max(msum + nums[i], nums[i]);
  17. mmax = Math.max(mmax, msum);
  18. }
  19. // 取左中右的最大值
  20. return Math.max(mmax, Math.max(lmax, rmax));
  21. }

56合并区间

思路:

  • 修改interval类,实现Comparable<Interval>的compareTo
  • Collections.sort(intervals)
  • 先将第一个元素放进res,然后遍历
    • 比较当前interval的start和res中最后一个interval的end,如果大于,说明不重叠,直接把当前interval添加到res;否则更改res最后一个interval的end为它本身end和当前interval的end之中的最大值。
  1. res.add(intervals.get(0));
  2. for (int i = 1; i < intervals.size(); ++i) {
  3. Interval curInterval = intervals.get(i);
  4. int lastIntervalEnd = res.get(res.size()-1).end;
  5. if (lastIntervalEnd < curInterval.start) {
  6. res.add(curInterval);
  7. } else {
  8. res.get(res.size()-1).end = Math.max(lastIntervalEnd, curInterval.end);
  9. }
  10. }

128最长连续序列

  1. 输入: [100, 4, 200, 1, 3, 2]
  2. 输出: 4
  3. 解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4

思路:题目要求O(n),所以不能用排序

  • 将数据加入set
  • 遍历
    • 删除遍历到的数,并设置pre、next指针,分别为num-1和num+1,循环搜索并删除set中pre和next所指代的数,并不断扩大pre和next,只要指针所指代的数不存在于set,该指针就停止扩大。循环后更新maxLen = next - pre + 1
  1. for (int num : nums) s.add(num);
  2. for (int num : nums) {
  3. if (s.remove(num)) {
  4. int pre = num - 1, next = num + 1;
  5. while (s.remove(pre)) --pre;
  6. while (s.remove(next)) ++next;
  7. // 注意,循环是在发现不存在时退出的,说明两个指针都多走了一步,所以下面+1-2
  8. res = Math.max(res, next - pre - 1);
  9. }
  10. }

674最长连续递增序列

思路:

  • 设置res记录最大值和cnt计数器
  • 遍历
    • 如果递增,cnt++,并更新res
    • 否则重置cnt = 1
  1. // 注意这里cnt和res的初始值
  2. int cnt = 1, res = 1, n = nums.length;
  3. if (n <= 1) return n;
  4. for (int i = 1; i < n; i++) {
  5. if (nums[i] > nums[i-1]) {
  6. cnt++;
  7. res = Math.max(res, cnt);
  8. }
  9. else cnt = 1;
  10. }
  11. return res;

45/55跳跃游戏

  1. // 55能否到达终点
  2. int n = nums.length, reach = 0;
  3. for (int i = 0; i < n; ++i) { // 实际上能够遍历到n-1已经说明能到达终点了,下面的i > reach判断了一些不能到达终点的情况。
  4. // i > reach 是用于跳进0的情况,此时不可能跳到最后
  5. if (i > reach || reach >= n - 1) break;
  6. // 不断更新当前能够到达的最远距离
  7. reach = Math.max(reach, i + nums[i]);
  8. }
  9. return reach >= n - 1;
  10. // 45假设总能到达终点
  11. int n = nums.length, curReach = 0, preReach = 0, cnt = 0;
  12. for (int i = 0; i < n; ++i) {
  13. curReach = Math.max(curReach, i + nums[i]);
  14. if (i == preReach) { // i小于preReach时更新curReach是为了确定下一步能够到达的最远距离。
  15. preReach = curReach;
  16. cnt++;
  17. if (preReach >= n - 1) break;
  18. }
  19. }
  20. return cnt;

41缺失的第一个正数

给定一个未排序的整数数组,找出其中没有出现的最小的正整数。

  1. 输入: [3,4,-1,1]
  2. 输出: 2

思路:

改造原数组,使得nums[0] = 1, nums[i] = i + 1。实现方法是遍历,当nums[i]所代表的数不超出数组坐标范围,而且它应该在的位置不等于它,即nums[i] != nums[nums[i] - 1],那么就交换,把它放到它应该在的index。遍历完就可以在遍历一次,检查哪个位置缺失了应该出现的值。如果没有,就返回n+1。

  1. int n = nums.length;
  2. for (int i = 0; i < n; i++){
  3. while (nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i] - 1]){
  4. swap(nums, i, nums[i] - 1);
  5. }
  6. }
  7. for (int i = 0; i< n; i++){
  8. if (nums[i] != i + 1) return i + 1;
  9. }
  10. return n + 1;

946验证栈序列

思路:

  • 新建一个栈
  • 遍历
    • 往栈添加push序列的元素
    • 如果栈不为空,而且栈顶等于pop序列,说明需要pop(pop序列另外设置一个指针)
  • 返回栈是否为空

66加一

思路:

  • 设置carry=1
  • 从后遍历,加carry,更新carry,判断carry是否等于1,即是否进1,是的话继续遍历,否的话就可以返回结果了。
  • 如果遍历后carr等于0,说明数组只由“9”组成,返回比原数组长度大1,且res[0] = 1即可,否则返回原数组。
  1. for (int i = n - 1; i >=0; i--){
  2. int digit = nums[i] + carry;
  3. nums[i] = digit % 10;
  4. carry = digit / 10;
  5. if (carry == 0) return nums;
  6. }

233数字1的个数

思路:https://www.cnblogs.com/xuanxufeng/p/6854105.html

  1. int res = 0;
  2. for (long i = 1; i <= n; i *= 10) {
  3. long a = n / i;
  4. long b = n % i;
  5. res += (a + 8) / 10 * i + (a % 10 == 1 ? b + 1 : 0);
  6. }
  7. return res;

84/85最大矩形

思路:

  • 先说一维数组求最大矩形面积:遍历,如果下一个是大于等于当前元素的,继续。否则开始往前遍历算面积,这个过程不断更新最小高度和res。
  • 扩展到二维:新建一个dp数组,根据当前值以及上一层的值来构造一维数组,并把这个数组代入上面的函数,即可计算到某一层为止的最大矩形面积。
  1. public int maximalRectangle(char[][] matrix) {
  2. int m = matrix.length, n = matrix[0].length;
  3. int res = 0;
  4. int[] dp = new int[n];
  5. for (int i = 0; i < m; i++) {
  6. for (int j = 0; j < n; j++) {
  7. dp[j] = matrix[i][j] == '0' ? 0 : dp[j] + 1;
  8. }
  9. res = Math.max(res, largestRectangleArea(dp));
  10. }
  11. return res;
  12. }
  13. public int largestRectangleArea(int[] heights) {
  14. int res = 0, n = heights.length;
  15. for (int i = 0; i < n; i++) {
  16. if (i + 1 < n && heights[i] <= heights[i + 1]) continue;
  17. int minH = heights[i];
  18. for (int j = i; j >= 0; j--) {
  19. minH = Math.min(heights[j], minH);
  20. int area = minH * (i - j + 1);
  21. res = Math.max(res, area);
  22. }
  23. }
  24. return res;
  25. }

347前K个高频元素

思路:

1.HashMap + PriorityQueue

2.HashMap + 桶排

桶排,即新建一个长度为最大频率的List数组,然后遍历map,在频率index上的list添加key。最后遍历输出输出结果。

697数组的度

给定一个非空且只包含非负数的整数数组 nums, 数组的度的定义是指数组里任一元素出现频数的最大值。

你的任务是找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

  1. 输入: [1, 2, 2, 3, 1]
  2. 输出: 2
  3. 解释:
  4. 输入数组的度是2,因为元素12的出现频数最大,均为2.
  5. 连续子数组里面拥有相同度的有如下所示:
  6. [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
  7. 最短连续子数组[2, 2]的长度为2,所以返回2.

思路:

  • 新建HashMap记录每个数字的freq和startIdx
  • 遍历,更新HashMap,如果当前数字的freq等于degree,那么更新长度,如果大于degree,那么更新长度和degree

88合并两个有序数组

  1. 输入:
  2. nums1 = [1,2,3,0,0,0], m = 3
  3. nums2 = [2,5,6], n = 3
  4. 输出: [1,2,2,3,5,6]

思路:

  • 类似合并两个有序链表,需要三个指针,两个数组各一个(从m-1和n-1开始),一个公共指针(从m+n-1开始)
  • 循环,只要其中一个不为空
    • 比较两个数组指针上的数谁大,大的填充到nums1[公共指针],并移动指针
  • 循环,把剩余的nums2填充到nums1

1两数之和

思路:用map存储遍历过的数及其index;每次遍历检查map中是否有所需补数

217存在重复元素

思路:set

扩展

排序数组中小于0的最大数的下标和大于0的最小数的下标。二分找0。未排序:维护两个长度为2的数组,类似于找最值。

leetcode数组相关的更多相关文章

  1. TSPL学习笔记(4):数组相关练习

    最近研究函数式编程,都是haskell和scheme交互着看的,所以笔记中两种语言的内容都有,练习一般也都用两种语言分别实现. 本篇练习一些数组有关的问题,之所以与数组相关是因为在命令式编程中以下问题 ...

  2. c语言中数组相关问题

    c语言中数组相关问题: 1.数组基本定义: 相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,然后用编号区分他们的变量的集合,这个名字称为数组名,编号称为下标.组成数组 ...

  3. Scala学习(三)----数组相关操作

    数组相关操作 摘要: 本篇主要学习如何在Scala中操作数组.Java和C++程序员通常会选用数组或近似的结构(比如数组列表或向量)来收集一组元素.在Scala中,我们的选择更多,不过现在我们先假定不 ...

  4. PHP基础系列(二) PHP数组相关的函数分类整理

    之前写过一篇介绍 PHP字符串函数 的博文,这里写第二篇,本文主要介绍PHP 数组相关的函数: 一.检查数组中是否存在 array_key_exists — 检查给定的键名或索引是否存在于数组中 ar ...

  5. 快学Scala习题解答—第三章 数组相关操作

    3 数组相关操作  3.1 编写一段代码.将a设置为一个n个随机整数的数组,要求随机数介于0(包括)和n(不包括)之间  random和yield的使用 import scala.math.rando ...

  6. leetcode tree相关题目总结

    leetcode tree相关题目小结 所使用的方法不外乎递归,DFS,BFS. 1. 题100 Same Tree Given two binary trees, write a function ...

  7. [LeetCode] [链表] 相关题目总结

    刷完了LeetCode链表相关的经典题目,总结一下用到的技巧: 技巧 哑节点--哑节点可以将很多特殊case(比如:NULL或者单节点问题)转化为一般case进行统一处理,这样代码实现更加简洁,优雅 ...

  8. Leetcode数组题*3

    目录 Leetcode数组题*3 66.加一 题目描述 思路分析 88.合并两个有序数组 题目描述 思路分析 167.两数之和Ⅱ-输入有序数组 题目描述 思路分析 Leetcode数组题*3 66.加 ...

  9. LeetCode 数组分割

    LeetCode 数组分割 LeetCode 数组怎么分割可以得到左右最大值的差值的最大 https://www.nowcoder.com/study/live/489/1/1 左右最值最大差 htt ...

随机推荐

  1. Git 分支创建

    分支策略:git上始终保持两个分支,master分支与develop分支.master分支主要用于发布时使用,而develop分支主要用于开发使用. 创建master的分支developgit che ...

  2. Spring学习_day03_事务

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! Spring_day03 一.事务 1.1 事务 事务 ...

  3. 【sqli-labs】 less46 GET -Error based -Numeric -Order By Clause(GET型基于错误的数字型Order By从句注入)

    http://192.168.136.128/sqli-labs-master/Less-46/?sort=1 sort=4时出现报错 说明参数是添加在order by 之后 错误信息没有屏蔽,直接使 ...

  4. Zabbix 客户端安装教程(第二篇)

    Zabbix 客户端安装教程 blog地址:http://www.cnblogs.com/caoguo [root@localhost ~]# yum install -y gcc make [roo ...

  5. 配置tfs2017的agent

    tfs支持四种验证方式,分别是:PAT.Negotiate.Integrated.Alternate 我们使用Negotiate方式 首先,登录tfs服务器,设置iis的身份验证  添加一个Negot ...

  6. 黑苹果开启retina,大分辨率的方法

    首先,管理分辨率RDM的软件这里下载: http://pan.baidu.com/s/1bpjL07P 在终端输入: curl -o ~/enable-HiDPI.sh https://raw.git ...

  7. 北京Python开发培训怎么选?

    北京的地理优势和经济优势基本无需多言,作为全国机会最多的地方,吸引了无数的北漂前赴后继.作为中国互联网中心之一,北京有海量Python岗位正在等待大家淘金. 近几年中,Python一直是市场上最受欢迎 ...

  8. 表单enctype属性传值问题

    form表单的enctype设置为multipart/form-data后,表单中除了文件后台能拿到,其他值后台都拿不到. 知识点: 一.application/x-www-form-urlencod ...

  9. kernel-常见参数或宏

    kernel-常见参数或宏 get_online_cpus get_online_cpus(); get_online_mems(); kstrdup_const 分配内存 cache_name = ...

  10. python之BeautifulSoup库

    1. BeautifulSoup库简介 和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据.lxml 只会局部遍历 ...