首页 > 编程语言 >算法入门(第二天)---双指针977,189

算法入门(第二天)---双指针977,189

时间:2023-01-11 18:56:42浏览次数:63  
标签:977 nums int --- start length 数组 189 left

977. 有序数组的平方

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/squares-of-a-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:
最简单的思路是直接平方后对数组进行简单排序,但是显然效率很低,所以考虑到影响平方后大小的情况只在于符号的变化,
主要有以下三种情况
1.所有数字都是负数,直接将数组平方后反向即可。
2.所有数字都是正数,直接将数组平方即可
3.有正有负,将找到负数和非负数的分界,对于负数(left)和正数(right)平方后的数比较,优先将小的数据填入辅助数组即可。
代码如下

public class Solution {
    public int[] sortedSquares(int[] nums) {
        int mid=0;
        int flag=0;
        if(nums[0]>0) flag=1;//最小为正数,全正数
        if(nums[nums.length-1]<0) flag=-1;//最大为负数,全负数
        for(int i=0;i<nums.length-1;i++)//进行平方
        {
            if(nums[i]<0&&nums[i+1]>=0)
            {
                mid=i;//找分界点
            }
            nums[i]=nums[i]*nums[i];
        }
        nums[nums.length-1]=nums[nums.length-1]*nums[nums.length-1];
        if(flag==1) return nums;//全正,直接平方后返回
        int [] midnums=new int[nums.length];//辅助数组
        if(flag==-1) {//全负,反转
           int left=0,right=nums.length-1;
           while(right>=0)
           {
               midnums[left]=nums[right];
               left++;
               right--;
           }
           return midnums;
        }
        int left=mid,right=mid+1;
        int index=0;
        while(left>=0&&right!=nums.length)
        {
            if(nums[left]<=nums[right])
            {
                midnums[index]=nums[left];
                left--;
            }
            else
            {
                midnums[index]=nums[right];
                right++;
            }
            index++;
        }//将小的优先填入
        if(index==nums.length) return midnums;//正好填完
        else if(index<nums.length&&left<0)//负数一侧已经填完,按序填充正数一侧
        {
            while(right!=nums.length)
            {
                midnums[index]=nums[right];
                right++;
                index++;
            }
        }
        else if(index<nums.length&&right==nums.length)//正数一侧已经填完,按序填充负数一侧
        {
            while(left>=0)
            {
                midnums[index]=nums[left];
                left--;
                index++;
            }
        }  
        return midnums;
}
}

我的代码最开始未考虑全正和全负的情况,加上后逻辑较为混乱,题解代码分类更加清晰

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        int negative = -1;
        for (int i = 0; i < n; ++i) {
            if (nums[i] < 0) {
                negative = i;
            } else {
                break;
            }
        }

        vector<int> ans;
        int i = negative, j = negative + 1;
        while (i >= 0 || j < n) {
            if (i < 0) {
                ans.push_back(nums[j] * nums[j]);
                ++j;
            }//全正数
            else if (j == n) {
                ans.push_back(nums[i] * nums[i]);
                --i;
            }//全负数
            else if (nums[i] * nums[i] < nums[j] * nums[j]) {
                ans.push_back(nums[i] * nums[i]);
                --i;
            }
            else {
                ans.push_back(nums[j] * nums[j]);
                ++j;
            }
        }
        return ans;
    }
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/squares-of-a-sorted-array/solution/you-xu-shu-zu-de-ping-fang-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

189. 轮转数组

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

 输入: 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]

 来源:力扣(LeetCode)
 链接:https://leetcode.cn/problems/rotate-array
 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法一.直接利用一个额外的数组空间对数据进行移位,然后重新赋值给nums即可

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

方法二.利用数组的逆转进行数据的移位,首先对整个数组进行转置,然后对0,k-1这前k个数据进行翻转,后对k,n-1的数组进行翻转即可实现k的移位

eg: nums = [1,2,3,4,5,6,7], k = 3
    7,6,5,4,3,2,1 
    5,6,7,4,3,2,1
    5,6,7,1,2,3,4移位成功
以下是我的代码

class Solution {
    public void reverse(int []nums,int start,int end)
    {
        while(start<end)
        {
            int mid=nums[start];
            nums[start]=nums[end];
            nums[end]=mid;
            start++;
            end--;
        }
    }
    public void rotate(int[] nums, int k) {
        int n=nums.length-1;
        if(k>=nums.length) k=k%nums.length;
        reverse(nums,0,n);
        reverse(nums,0,k-1);
        reverse(nums,k,n);
    }
}

方法三.利用双指针,和数学关系进行移位

从位置0开始,令temp=nums[0],然后对0元素进行k的移位即令nums[(0+k)%n]与temp进行交换,然后对nums[k]进行移位直到最终回到开始位置0,由此我们完成了0的剩余系的移位,然后我们需要取下一个剩余系的起始位置,但是这个位置怎么取呢?

由于最终回到了起点,故该过程恰好走了整数数量的圈,不妨设为 a 圈;再设该过程总共遍历了 b 个元素。因此,我们有an=bk,即 an 一定为 n,k的公倍数。又因为我们在第一次回到起点时就结束,因此 a 要尽可能小,故 an 就是 n,k的最小公倍数 lcm(n,k),因此 b=lcm(n,k)/k。
这说明单次遍历会访问到lcm(n,k)/k 个元素。为了访问到所有的元素,我们需要进行遍历的次数为
n/lcm(n,k)/k=gcd(n,k)
所以遍历前 gcd(n,k)个元素即可

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);
        }
    }

    public int gcd(int x, int y) {
        return y > 0 ? gcd(y, x % y) : x;
    }
}

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode-solution-nipk/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:977,nums,int,---,start,length,数组,189,left
From: https://www.cnblogs.com/zz-gy/p/17044654.html

相关文章

  • percona-toolkit运维工具
    参考MySQL基础运维——percona-toolkit运维工具_ITPUB博客一、percona-toolkit工具percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦......
  • 容器化-Docker-5-Docker容器
    目录Docker容器管理(操作对象是容器)通过一个镜像创建一个容器查看已启动的容器列表启、停、重启、删除已经在容器列表的容器如何进入退出容器查看容器使用的资源inspect检......
  • Redis-多机数据库-复制
    复制在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的......
  • 【深入浅出 Yarn 架构与实现】4-4 RM 管理 Application
    在YARN中,Application是指应用程序,它可能启动多个运行实例,每个运行实例由—个ApplicationMaster与一组该ApplicationMaster启动的任务组成,它拥有名称、队列、优先级......
  • k8s-新增master节点
    在当前唯一的master节点上运行如下命令第一步:kubeadminitphaseupload-certs--upload-certs执行结果如下:1#kubeadminitphaseupload-certs--upload-cert......
  • 上市公司数字化转型数据(1990-2021)
    上市公司数字化转型数据(1990-2021)​上市公司数字化转型数据(1990-2021)上市公司数字化转型数据(1990-2021) 最新版数据已整理为Excel格式,数据的时间区间为1990-2021年,内含“数......
  • buuctf-preg_replace的e模式造成命令执行
    [BJDCTF2020]ZJCTF,不过如此打开后是正常的代码审计首先第一眼看到的就是file_get_contents而且还对$text有要求,直接上伪协议data://text/plain,Ihaveadream,同时按照......
  • 【接口自动化测试】Python基础-字符串格式化
    """字符串格式化"""name='Jenny'age=30x="mynameis%s,ageis20"%nameprint(x)x1="mynameis%s,ageis%s"%(name,age)print(x1)#第二种y="myname......
  • Dockerfile制作jdk-17
    下载jdk-17#wgethttps://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gzDockerfileFROMubuntu:22.04ENVJAVA_HOME=/usr/local/jdk-17.0.5ENV......
  • nth-of-type
    .menu-item:nth-of-type(2).menu-imgwidth90pxheight90px.menu-item:nth-of-type(3).menu-imgwidth78pxheight90px.menu-item:nth-of-type(4).menu-......