数组及排序LeetCode刷题记录

2021-01-21 08:12

阅读:870

标签:顺序   否则   自己   rgs   find   ||   int   重写   for循环   

2、数组_排序

刷题总结:一般数组逃不过这些方法方法

  • 双指针:一个从头遍历,一个从尾遍历
  • 三指针:一个从头遍历,一个从尾遍历,一个遍历数组本身,找满足条件的进行交换
  • 从后向前遍历,从后向前填充!

75、颜色分类

方法:三指针

  • 为什么用多指针?
  1. 题目说遍历一次数组解决问题,一般都是用多指针!

三个指针各司其职:

  1. 第一个在左边确定 0 的位置
  2. 第二个在右边确定2的位置
  3. 第三个遍历数组:寻找 0 和 2 进行交换,把它与第一个指针或者第二个指针交换!
package 数组排序;


import java.util.Arrays;

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/4/26 9:02
 * 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
 *
 * 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
 *
 * 注意:
 * 不能使用代码库中的排序函数来解决这道题。
 *
 * 示例:
 *
 * 输入: [2,0,2,1,1,0]
 * 输出: [0,0,1,1,2,2]
 * 进阶:
 *
 * 一个直观的解决方案是使用计数排序的两趟扫描算法。
 * 首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
 * 你能想出一个仅使用常数空间的一趟扫描算法吗?
 *
 * 来源:力扣(LeetCode)
 * 链接:https://leetcode-cn.com/problems/sort-colors
 * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
 */
public class _75_颜色分类 {
    /**
     分析:1、原地排序、常数空间都说明:空间复杂度:O(1)
          2、一趟扫描多数使用 双指针或者 三指针
     本题采用三指针!
     */
    public void sortColors(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        int p = 0;
        while (p 

88、合并两个有序数组

  • 分析:

方法:从后向前遍历,满足条件填充

其实这一题和合并两个有序链表类似,不过这一题是 从右向左遍历,说白了就是先给大的值找到适当的位置!

因为如果找小的会被覆盖,导致值丢失,这时候换个角度岂不美哉!

  • 自己写的
给你两个有序整数数组?nums1 和 nums2,请你将 nums2 合并到?nums1?中,使 nums1 成为一个有序
?
说明:
初始化?nums1 和 nums2 的元素数量分别为?m 和 n 。
你可以假设?nums1?有足够的空间(空间大小大于或等于?m + n)来保存 nums2 中的元素。
?
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3
输出:?[1,2,2,3,5,6]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码:
  		int i = m - 1;
        int j = n - 1;
        int k = m + n - 1;
        while (i >= 0 && j >= 0) {
            if (nums1[i] >= nums2[j]) {
                nums1[k--] = nums1[i--];
            } else {
                nums1[k--] = nums2[j--];
            }
        }
        while (i >= 0) {
            nums1[k--] = nums1[i--];
        }
        while (j >= 0) {
            nums1[k--] = nums2[j--];
        }
  • 最优解,相当于用归并排序优化!

我们要做的就是把第二个数组归并到第一个数组中,所以第二个数组必须扫描完,第一个退出直接将第二个接到后面!

技术图片
  • 帅气的代码!
int i = m - 1;
int j = n - 1;
int k = m + n - 1;
while (j >= 0) {
    if (i >= 0 && nums1[i] >= nums2[j]) {
        nums1[k--] = nums1[i--];
    } else {
        nums1[k--] = nums2[j--];
    }
}

面试题16.16部分排序

方法:本质上还是双指针

  1. 两次遍历一次从头开始,一次从末尾开始,找到 m 和 n
  2. 找到最大逆序对,用到了数学知识,逆序对就是 本来从小到大的,结果后面的比前面最大的小

实现:

package 数组排序;

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/4/26 10:22
 * 给定一个整数数组,编写一个函数,找出索引m和n,只要将索引区间[m,n]的元素排好序,整个数组就是有序的。注意:n-m尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n],若不存在这样的m和n(例如整个数组是有序的),请返回[-1,-1]。
 *
 * 示例:
 *
 * 输入: [1,2,4,7,10,11,7,12,6,7,16,18,19]
 * 输出: [3,9]
 *
 * 来源:力扣(LeetCode)
 * 链接:https://leetcode-cn.com/problems/sub-sort-lcci
 * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
 */
public class _面试题16_16_部分排序 {
    public int[] subSort(int[] array) {
        if (array == null || array.length == 0) {
            return new int[]{-1, -1};
        }
        int n = findN(array);
        int m = findM(array);
        return new int[]{m, n};
    }

    private int findN(int[] array) {
        //找最大逆序对的位置
        int n = -1;
        int max = array[0];
        for (int i = 1; i = max) {
                max = array[i];
            } else {
                n = i;
            }
        }
        return n;
    }
    private int findM(int[] array) {
        //找最大逆序对的位置
        int m = -1;
        int min = array[array.length - 1];
        for (int i = array.length - 1; i >= 0; i--) {
            if (array[i] 

复杂度:O(n)

可以优化成一次遍历 : 不过复杂度一样,因为for循环中执行的总代码数一样

if (array == null || array.length == 0) {
    return new int[]{-1, -1};
}
//优化成遍历一次
int m = -1, n = -1;
int len = array.length;
int max = array[0],min = array[len - 1];
for (int i = 1; i = max) {
        max = array[i];
    } else {
        n = i;
    }
    if (array[len - i - 1] 

很强,不过要注意边界问题!要保证两边都得遍历完

977、有序数组的平方

方法:

又是双指针,所以说,数组逃不掉指针!

package 数组排序;

import java.util.Arrays;

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/4/26 11:48
 * 给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。
 *
 *  
 *
 * 示例 1:
 *
 * 输入:[-4,-1,0,3,10]
 * 输出:[0,1,9,16,100]
 * 示例 2:
 *
 * 输入:[-7,-3,2,3,11]
 * 输出:[4,9,9,49,121]
 *
 * 来源:力扣(LeetCode)
 * 链接:https://leetcode-cn.com/problems/squares-of-a-sorted-array
 * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
 */
public class _977_有序数组的平法 {
    public int[] sortedSquares(int[] A) {

/*        //1、low的方法
        for (int i = 0; i  r) {
            ans[cur--] = (A[j]*A[j] >= A[r]*A[r]) ? (A[j]*A[j--]) : (A[r]*A[r++]);
        }
        return ans;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{-4,-1,0,3,10};
        int[] ints = new _977_有序数组的平法().sortedSquares(arr);
        System.out.println(Arrays.toString(ints));
    }
}

数组还有个喜欢考的,就是二分查找,就是要求数组必须有序

但是这一题做到了无序问题,我不知道意义何在?

package 数组排序;

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/4/27 15:31
 * 假设按照升序排序的数组在预先未知的某个点上进行了旋转。
 *
 * ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
 *
 * 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
 *
 * 你可以假设数组中不存在重复的元素。
 *
 * 你的算法时间复杂度必须是 O(log n) 级别。
 *
 * 示例 1:
 *
 * 输入: nums = [4,5,6,7,0,1,2], target = 0
 * 输出: 4
 * 示例 2:
 *
 * 输入: nums = [4,5,6,7,0,1,2], target = 3
 * 输出: -1
 *
 * 来源:力扣(LeetCode)
 * 链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
 * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
 */
public class _33_搜索旋转排序链表 {
    public int search(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;
        int begin = 0;
        int end = nums.length - 1;
        while (begin > 1;
            int res = nums[mid];
            if (target == res) return mid;
            if (nums[0] = nums[0]) {
                    end = mid - 1;
                } else {
                    begin = mid + 1;
                }
            } else {
                //右边有序
                if (target > res && target 

560、和为K的子数组数

没用到数组的经典算法,算是简单的题

  • 按照我的思路,题解写在代码上
package 数组排序;

import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangbingbing
 * @version 1.0
 * @date 2020/5/15 10:19
 * 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
 * 

* 示例 1 : *

* 输入:nums = [1,1,1], k = 2 * 输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。 *

* 来源:力扣(LeetCode) * 链接:https://leetcode-cn.com/problems/subarray-sum-equals-k * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 */ public class _560_和为K的子数组数 { //枚举算法的想法也是遍历的时候想到每一步要干嘛,在进行暴力枚举! public int subarraySum(int[] nums, int k) { if (nums == null) return 0; int count = 0; //枚举枚举肯定要遍历关键是每次遍历我们要干什么:**求出它的前面的所有子数组和** for (int i = 0; i = 0; j--) { sum += nums[j]; if (sum == k) { count++; } } } return count; } //优化成哈希表,难,像是动态规划的递推 public int subarraySum2(int[] nums, int k) { int count = 0, sum = 0; //我们用map来存储 Map map = new HashMap(); map.put(0,1); for (int i = 0; i

都是用心的总结,望点赞,评论讨论!!

数组及排序LeetCode刷题记录

标签:顺序   否则   自己   rgs   find   ||   int   重写   for循环   

原文地址:https://www.cnblogs.com/bingstudy/p/12897703.html


评论


亲,登录后才可以留言!