T283移动0——Java实现

T283题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

解法一

思路

  • 定义两个指针ab
  • a指针用于遍历数组查找非0元素b指针在后面用于接收a指针找到的非0元素
  • a指针到达数组末尾时,非0元素已经全部完成重新覆盖数组
  • 将剩下的元素用0覆盖

代码

//方法体
public void moveZeroes(int[] nums) {
        
        int j=0;
        for(int i=0;i<nums.length;i++){
            if(nums[i] != 0){
                nums[j] = nums[i];
                j++;
            }
        }
        //注意:跳出循环时,j已经在最后一个非0元素下标的基础上,加了一个1,所以,直接从j开始用0覆盖
        for(int i=j;i<nums.length;i++){
            nums[i] = 0;
        }
        for (int num : nums) {
            System.out.println(num);
        }
    }

解法二

思路

  • 定义两个指针ab
  • 模拟情景:同学A和同学B肩并肩走在路上,突然他们发现马路上坑,由于同学A有轻功,不受“坑”的影响,同学B年年体育不达标,于是两人商量着,由同学A继续向前走寻找井盖,而同学B留下来等待同学A给他送来井盖,这样他就能继续往后走了,等到同学A找到了井盖,就将井盖抛给同学B,让他前进,若路上没有看见未盖上的井口,同学A不想等同学B,只想自己着在同学B遇到“坑”的时候再给它送个井盖,然后快点到终点,剩下的事它就不管了…等到同学A已经到达这段危险路段的终点时,同学B还在徘徊,因为…去终点的路上全是坑,已经没有井盖可以填补了…
  • 上述例子中,未盖上的井口为0,盖上的井口为非0

代码

public void moveZeroes(int[] nums) {

        int j=0;
        for(int i=0;i<nums.length;i++){
            /*
            下列注释掉的代码为分步骤执行的代码
             */
            
            //没碰到“坑”就都继续往后走
//            if(nums[i]!=0 && nums[j]!=0){
//                j++;
//            }
            
            //两个人都碰到了坑,那也没办法,前面那个坑还没填好,那么同学B只能继续等待,同学A则继续往后找井盖
//            else if(nums[i]==0 && nums[j]==0){
//                continue;
//            }
            
            //同学A找到了井盖,并给同学B补“坑”,补完之后,同学B就可以继续往后走了,同学A有轻功,不受“坑”的影响,同时,它也不想等同学B,只想自己着在同学B遇到“坑”的时候再给它送个井盖,然后快点到终点,剩下的事它就不管了
//            else if (nums[i]!=0 && nums[j]==0){
//                int temp = nums[i];
//                nums[i] = 0;
//                nums[j] = temp;
//                j++;
//            }
            
            //同学A遇到了“坑”,同学B还没遇到,同学A不吭声,继续向前走,同学B不知道前面有个“坑”,他也会继续向前走,因为他迟早会遇到
//            else if(nums[i]==0&&nums[j]!=0){
//                j++;
//            }
            
            //简写代码
            if(nums[i]!=0){
                if(nums[j]==0){
                    int temp = nums[i];
                    nums[i] = 0;
                    nums[j] = temp;
                }
                j++;
            }
        }
        for (int num : nums) {
            System.out.println(num);
        }
    }

解题收获

错误点

  • 一开始我是想将各个0的下标记录下来,之后利用这些下标对数组进行分段,每一段分别向前移动不同的位数(前面有几个0就移动几位),发现这样不现实,因为在移动的过程中数组是变化的,这样之前记录的下标就不稳定了,导致过程很复杂,最后也没有将思路实现,这很可惜。
  • 后来我的想法是碰到一个0就往前移动,移动后指针指向的元素就不是0了,若是继续向后遍历,势必会出错,也意味着一个指针做不到,使用for循环会很麻烦。

疑惑点

解法二提到借用了快速排序的思想,但我很懵…,需要再将快速排序的算法看一遍

原大佬的解释如下:

这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点x,然后把所有小于等于x的元素放到x的左边,大于x的元素放到其右边。
这里我们可以用0当做这个中间点,把不等于0(注意题目没说不能有负数)的放到中间点的左边,等于0的放到其右边。
这的中间点就是0本身,所以实现起来比快速排序简单很多,我们使用两个指针i和j,只要nums[i]!=0,我们就交换nums[i]和nums[j]

等我将快排理解完后再回来看这句话~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
移动臂调度算法(Scan Algorithm)是一种磁盘调度算法,用于确定磁盘上磁道的顺序访问。在此算法中,磁头沿着一个方向移动,当到达最边缘时,它会反向移动,并继续扫描下一个磁道。 要实现移动臂调度算法Java代码,可以按照以下步骤进行: 1. 首先,定义一个函数来计算磁道访问的总时间。该函数接受两个参数:当前磁道位置和下一个要访问的磁道位置。 2. 在函数中,首先计算磁道之间的差值(即磁头需要移动的距离),并将其求绝对值。这个距离就是访问时间的一部分。 3. 然后,将磁头移动到下一个磁道位置,并将新位置设置为当前磁道位置。 4. 重复步骤2和步骤3,直到所有磁道都被访问完毕。 以下是一个简单的移动臂调度算法Java实现示例: ```java public class DiskScheduler { public static void main(String[] args) { int[] tracks = { 30, 45, 12, 18, 5, 10, 25 }; int currentTrack = 15; int totalAccessTime = 0; // Sort the tracks in ascending order Arrays.sort(tracks); // Iterate through each track for (int i = 0; i < tracks.length; i++) { int nextTrack = tracks[i]; // Calculate the absolute difference in track positions int distance = Math.abs(currentTrack - nextTrack); // Add the distance to the total access time totalAccessTime += distance; // Set the new current track position currentTrack = nextTrack; } System.out.println("Total access time: " + totalAccessTime); } } ``` 在这个示例中,磁道位置使用一个整数数组来表示,`currentTrack`变量表示当前磁道的位置。`totalAccessTime`变量用于计算总的磁道访问时间。 首先,将磁道位置进行排序,以便按升序访问。然后,通过计算当前磁道位置与下一个磁道位置之间的距离来计算访问时间。该距离添加到总的访问时间中,并将新的磁道位置设置为当前磁道位置。 最后,输出总的访问时间。 注意:这只是一个简单的示例,实际应用中可能需要考虑更多的情况和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值