算法之001RotateArray

最重要的是思想,要敢于想才行。

不会算法的人,就一条,思想上的懒惰。现在慢慢发现,很多时候,人们现在行动上,好像都知道不能懒惰,从小到大,都被教育不能懒惰。但是还有一种更深层次的懒惰就是思想懒。不想自己动脑筋,习惯灌输式学习。其实可以多睡觉,但是思想上不能懒惰。要乐于思考才行。

- 思路整理
当做一件事,感觉有很多种思路。这往往是说明你善于分析,有很多种想法。这个时候要注意了,因为你如果没有指导思想,那么想法多可能会害了你。
- 图解解决有多个思路的问题的指导思想
遇到一个问题,当我们有很多个想法的时候,是最好的,几乎每一种想法,都会有价值,让你掌握经验,最重要的是,你要根据经验选择一种进行研究下去,然后就能解决问题。经历有限,时间有限,这个时候就是体现你是否有足够经验的时候了。也就是为什么要强调经验的重要性。(当年高考的时候,我想想自己解题的时候,多个思路,同时去尝试的那种傻傻的方式。还有没有范例驱动去学习的愚蠢。)
这里写图片描述


编码能力和程序设计能力完全是两回事。
重要的是掌握思路算法,而不是一门语言。这个至关重要。
唯一的问题是你不愿意静下心来好好看书,太急躁了而已。

189Rotate Array

Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.

可能不是最优解,但是需要有一种解决问题的思路。
从核心开始思考,然后完善。
大概的意思是

K数组数据
K=0[1,2,3,4,5,6,7]
k=1[7,1,2,3,4,5,6]
k=2[6,7,1,2,3,4,5]
k=3[5,6,7,1,2,3,4]

有了这个思路后,就大概知道题目的意思了。就是每一次都把上一次最后面的那个数放到最前面(用temp记录下来,等第一位位置的数移动到他应该移动的位置后,再把temp值放到第一个位置a[0]),其他位置的数依次向后挪动一个位置()。

int temp = nums[length-1];
for (int j = length -1; j > 0; j--) {
    nums[j] = nums[j-1];
}
nums[0]= temp;

接下来考虑当k=3时候,如何循环的问题。

可以看到。其实k每次加1都是在上一次中的一个完整的数组基础上执行一次同样的过程。这个时候,我们就容易想到,只要完全执行这段代码k次就

for (int i = 0; i < k; i++) {
    int temp = nums[length-1];
    for (int j = length -1; j > 0; j--) {
        nums[j] = nums[j-1];
    }
    nums[0]= temp;
}

到此这个算法的初步就已经完成了。最重要的还是思路。不过上面这个算法是最直观的算法。但是移动次数较多,k=n,就要移动k*n次。而且循环的次数也是k*n次O(k*n)
好了到此就贴出整个完整的代码。
整体算法搞定后,就可以考虑一些细枝末节了,比如边界问题。
k的取值应该是0-7之间的整数。这个读者可以自己加入。

package leet.array;

public class RotateArray189 {

    public void rotate(int[] nums,int k){
        int length = nums.length;
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }
        System.out.println();
        for (int i = 0; i < k; i++) {
            int temp = nums[length-1];
            for (int j = length -1; j > 0; j--) {
                nums[j] = nums[j-1];                
            }
            nums[0]= temp;
        }
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }
    }

    public static void main(String[] args) {
        RotateArray189 rotateArray189 = new RotateArray189();
        int[] a = {1,2,3,4,5,6,7};
        int k = 3;

        rotateArray189.rotate(a, k);
    }

}

这里这个k的取值在我们这个算法中其实是可以不做过多限制。因为我们在移动的时候,要求k>0才开始for循环的。

改进1

不让数组移动k次,而是移动1次。

public void rotate1(int[] nums ,int k){
        //加入对k的取值处理
        k %= nums.length;
        int[] tem = new int[k];
        //1记录后k个数据:(这个顺序倒着正着都可以,自己转换的时候记得就可以[5,6,7]=>[7,6,5])
        for (int i = 0; i < k; i++) {
            tem[i] = nums[nums.length-1-i];
        }
        //2前n-k个分别向后移动后k个位置
        for (int i = nums.length - 1 - k; i >= 0; i--) {
            nums[i+k] = nums[i];
        }
        //3后记录的k个位置的信息放到最前面
        for (int i = 0; i < k; i++) {
            nums[i]=tem[k-1-i];
        }
        //4打印rotate之后的信息
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i]+" ");
        }
    }

如果用的是第二个方法,那么要考虑边界问题。
错误边界方式1:
if(k<0||k>nums.length)
{
return;
}
正确的边界方式:
(对k值进行处理就行了。)
k %= nums.length;

后记:越是心思缜密的人,越能做好算法,考虑的全面所以更擅长。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值