数据结构-LeetCode刷题(数组)

(LeetCode 1)两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。

方法一 暴力解决

暴力解决,从头到尾遍历数组,找出相加符合目标值的两值

  • 问题已理解
    如果面试遇到不会的,暴力解决也不失为一种办法,1总比0好,可能在叙述暴力解决办法的过程中就发现了可以改进的地方。
 public int[] twoSum(int[] nums, int target) {
       int[] result = new int[2];
       for(int i = 0;i < nums.length;i++){
           for(int j = i + 1;j < nums.length;j++){
               if(nums[i]+nums[j] == target){
                   result[0] = i;
                   result[1] = j;
                   return result;
               }
           }
       }
       return result;
   }

方法一 改进

依旧是使用HashMap,遍历第一个数时,在Map里找它相加等于目标值的值没有就将它添加进去;再遍历第二个值,这样,只遍历数组一次就解决了问题。

  • 问题已理解
 public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> storeNums = new HashMap<>(nums.length,1);
        //这里的第一个参数nums.length表示该HashMap对象的初始容量,
        //第二个参数1表示哈希表的负载因子,即哈希表在达到负载因子时会自动扩容。
        int[] result = new int[2];
        for(int i = 0;i < nums.length;i++){
            int another = target - nums[i];
            //该Map的键值对是index为值,value是键
            Integer anotherIndex = storeNums.get(another);
            //找到就返回下标
            if(null != anotherIndex){
                result[0] = anotherIndex;
                result[1] = i;
                break;
            }else{
                //没找到就返回遍历到的数和对应下标
                storeNums.put(nums[i],i);
            }
        }
        return result;
    }

运行结果

(LeetCode 88)合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2
的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m
个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

方法一 先合并再排序

先合并再排序,但这样破坏原有顺序

public void merge(int[] nums1, int m, int[] nums2, int n) {
        for(int i = 0;i < n;++i){
            nums1[m+i] = nums2[i];
        }
        Arrays.sort(nums1);
    }

方法二 从后往前比较元素大小

为了不破坏原有的顺序,我们可以从后往前比较俩数组元素的大小,大的放在nums1的后面的位置

  • 问题已理解
 public void merge(int[] nums1, int m, int[] nums2, int n) {
        int p = m + n - 1;
        int p1 = m - 1;
        int p2 = n - 1;

        while(p1 >= 0 && p2 >= 0){
            if(nums1[p1] >= nums2[p2]){
                nums1[p] = nums1[p1];
                p1--;
            }else{
                nums1[p] = nums2[p2];
                p2--;
            }
            p--;
        }   
        while(p2 >= 0){
            //nums1已经取完,直接取nums2
            nums1[p] = nums2[p2];
            p2--;
            p--;
        }
    }

运行结果

(LeetCode 283)移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作

方法 非零在前,零在后

遍历数组,遇到非零的数字按顺序添加在数组前面,并记录个数;数组遍历完后,直接将数组剩下的位置的元素赋值成0

  • 问题已理解
public void moveZeroes(int[] nums) {
        if(nums == null){
            return;
        }
        //第一次遍历,j记录非0的个数,只要遍历过程中遇到非零的数,就赋给nums[j]
        int j = 0;
        for(int i = 0;i <nums.length;i++){
            if(nums[i]!=0){
                nums[j++] = nums[i];
            }
        }
        //第二次遍历将剩下队尾的元素全赋值成0
        for(int i = j;i<nums.length;i++){
            nums[i] = 0;
        }
    }

运行结果

(LeetCode 448)找到数组中消失的数字

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题

方法 遍历修改元素,看最后没被修改的元素位置

遍历数组,根据数组元素的 值-1 找到对应位置上的元素,加上n(或>=n)值。
总之就是把数组元素的值看成对应的位置,修改对应位置的元素,且能让机器识别出来确实是修改后的数据(如大于某一值),然后遍历数组元素,找出没被修改的元素,位置+1(+ -1是因为数组从0开始计数)

  • 问题已理解
  public List<Integer> findDisappearedNumbers(int[] nums) {
        int n = nums.length;
        for(int num:nums){
            int x = (num - 1) % n;
            nums[x] += n;
        }

        List<Integer> result = new ArrayList<Integer>();
        for(int i = 0;i < n;i++){
            if(nums[i] <= n){
                result.add(i + 1);
            }
        }
        return result;
    }

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值