力扣初级算法练习Day02


前言

今天健完身,休息了会来实验室做算法题,刚开始没状态,后来还可以。


一、旋转数组

题目:给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

摘要:数组、向右轮转k个位置、k是非负数;

原思想:我想法很普通,完全是出于代码的逻辑,就是定义一个新数组,然后遍历传入的参数数组,每次遍历使新数组的下标等于参数数组的下标与轮转数k的和,如果和比参数数组要大,说明轮转已经超过了数组的长度,需要在轮转到数组最大长度后重头再来,那么就使得新数组的下标等于参数数组的下标与轮转数k的和再减去参数数组的长度,然后将参数数组的值赋值给新数组;否则,直接将参数数组的值赋值给旧数组;

原代码

class Solution {
    public int[] rotate(int[] nums, int k) {
        int j=0;
        int m = nums.length;
        int[] nums2 = new int[m];
        for(int i=0;i<nums.length;i++){
            j=i+k;
            if(j>nums.length-1){
                j=j-nums.length;
                nums2[j]=nums[i];
            }
            else{
                nums2[j]=nums[i];
            }            
        }
        return nums2;
    }
}

问题
使用了新数组,空间消耗大,方法没有技巧性;

新思想:
1.不使用新数组,设置一个临时变量temp,并且可以用求余数的方法得到新数组的下标,即 (i+k) mod nums.length;
2.数组翻转,当我们将数组的元素向右移动 kk次后,尾部 kmod n个元素会移动至数组头部,其余元素向后移动 kmod n个位置。
该方法为数组的翻转:我们可以先将所有元素翻转,这样尾部的 kmod n 个元素就被移至数组头部,然后我们再翻转 [0, kmod n-1]区间的元素和 [kmod n, n-1] 区间的元素即能得到最后的答案。
在这里插入图片描述

对于1思想的新代码:

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;

        int[] news = Arrays.copyOf(nums,n);

        for (int i = 0; i < n; i++) {
            nums[(i+k)%n] = news[i];
        }
    }
}

对于2思想的新代码:

class Solution {
    public void rotate(int[] nums, int k) {
        k %= nums.length;
        reverse(nums, 0, nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }

    public void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start += 1;
            end -= 1;
        }
    }
}

二、存在重复元素

题目:给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false;

摘要:整数数组、任一值出现至少两次返回true、任意元素互不相同返回false;

原想法
两次遍历,如果第一次遍历的值和第二次遍历的值相等,说明有重复的返回true,如果遍历完都么有值相等的,则返回false;

原代码

class Solution {
    public boolean containsDuplicate(int[] nums) {
        int temp;
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){
                if(nums[i]==nums[j]){
                    return true;
                }
            }
        }
        return false;
    }
}

问题
用了两次循环,时间复杂度高;

新思想
1.先排序后遍历,排序之后元素都按顺序排列,只需比较前后元素即可;
2.使用集合或者哈希表,创建新的集合或者哈希表,如果插入不成功,则说明有重复的;

对于思想1的新代码

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        for (int i = 0; i < n - 1; i++) {
            if (nums[i] == nums[i + 1]) {
                return true;
            }
        }
        return false;
    }
}

对于思想2的新代码

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set = new HashSet<Integer>();
        for (int x : nums) {
            if (!set.add(x)) {
                return true;
            }
        }
        return false;
    }
}

总结

1.这两道题都做出来了,但么有考虑解决问题的复杂性;
2.求余数的思想

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值