leetcode从零开始1

目录

977.给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

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


977.给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

1、自己的方法:(先平方再排序)

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var sortedSquares = function(nums) {
    let newArr=[]
    //先全部平方
    for(let i = 0;i<nums.length;i++){
        newArr.push(nums[i]*nums[i])
    }
    //再返回排序结果
    return newArr.sort((a,b)=>(a-b))
};

2、双指针的方法

解题思路:方法一没有利用「数组 nums 已经按照升序排序」这个条件。

这样一来,如果我们能够找到数组nums 中负数与非负数的分界线,那么就可以用类似归并排序的方法了。具体地,我们设negative 为数组 nums 中负数与非负数的分界线,也就是说,nums[0] 到 nums[negative] 均为负数,而 nums[negative +1] 到nums[n−1] 均为非负数。当我们将数组 nums 中的数平方后,那么 nums[0] 到 nums[negative] 单调递减,nums[negative +1] 到 nums[n−1] 单调递增。

具体地,使用两个指针分别指向位置negative 和negative +1,每次比较两个指针对应的数,选择较小的那个放入答案并移动指针。当某一指针移至边界时,将另一指针还未遍历到的数依次放入答案。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int negative=-1;
        for(int i=0;i<n;i++){
            if(nums[i]<0)
                negative=i;
            else{
                break;
            }
        }
        int[] ans= new int[n];
        int index=0,i=negative,j=negative+1;
        while(i>=0||j<n){
            if(i<0){
                ans[index]=nums[j]*nums[j];
                ++j;
            }else if(j==n){
                ans[index]=nums[i]*nums[i];
                --i;
            }else if(nums[i]*nums[i]<nums[j]*nums[j]){
                ans[index]=nums[i]*nums[i];
                --i;
            }else{
                ans[index]=nums[j]*nums[j];
                ++j;
            }
            ++index;
        }
        return ans;
    }
}

3、双指针

可以使用两个指针分别指向0和n-1,每次比较两个指针对应的数,选择较大的那个放在返回数组ans,逆序放置。这种方法的好处是:无需处理指针移动移动到边界的情况。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n =nums.length;
        int i,pos,j;
        int[] ans= new int[n];
        for(i=0,pos=n-1,j=n-1;i<=j;){
            if(nums[i]*nums[i]>nums[j]*nums[j]){
                ans[pos]=nums[i]*nums[i];
                ++i;
            }else{
                ans[pos]=nums[j]*nums[j];
                --j;
            }
            --pos;
        }
        return ans;
    }
}

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

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

1、自己先做的(数组翻转)

class Solution {
    public void rotate(int[] nums, int k) {
        int n=nums.length;
        k=k%n;//当k大于n时实际位移个数为k mod n
        Reverse(0,n-k-1,nums);
        Reverse(n-k,n-1,nums);
        Reverse(0,n-1,nums);
    }
    void Reverse(int start,int end,int[] a){
        int temp;
        while(start<end){
            temp = a[start];
            a[start]=a[end];
            a[end]=temp;
            start++;
            end--;
        }
    }
}

2、使用额外的数组

使用一个新的数组来将每个元素存放到正确的位置。用n表示数组长度,遍历原数组,将原数组下标为i的元素存放到新数组下标为(i+k)%n 的位置,最后将新数组拷贝到原数组中去。

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] newArr=new int[n];
        for(int i=0;i<n;i++){
            newArr[(i+k)%n]=nums[i];
        }
        System.arraycopy(newArr,0,nums,0,n);
    }  
}

3、环状替换(这个方法有点困难,暂时先了解即可)

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k = k % n;
        int count = gcd(k, n);
        for (int start = 0; start < count; ++start) {
            int current = start;
            int prev = nums[start];
            do {
                int next = (current + k) % n;
                int temp = nums[next];
                nums[next] = prev;
                prev = temp;
                current = next;
            } while (start != current);
        }
    }

    
    //求x和y的最大公约数
    public int gcd(int x, int y) {
        return y > 0 ? gcd(y, x % y) : x;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值