题目描述
给定一个整数数组 nums,将数组中的元素向右轮转 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]
思路及实现
My first method
截取
思路: 定义一个长度为k的数组截取nums数组前k位,然后从数组的后面依次向前移动k个位置,最后把截取的数组,填充到K个位置起,2k-1为位置即可。
实现:
具体代码实现:
public class Demo1 {
public static void main(String[] args) {
//问题描述:
Scanner sc = new Scanner(System.in);
System.out.println("请输入向右轮转的位数(非负数):");
int k = sc.nextInt();
System.out.println("请输入数组的长度:");
int length = sc.nextInt();
int[] nums = new int[length];
for (int i = 0; i < nums.length; i++) {
nums[i] = sc.nextInt();
}
//copyOf复制指定的数组,使用零截断或填充(如有必要),以使副本具有指定的长度。
int[] newHead = Arrays.copyOf(nums , k);
for (int i = nums.length; i > k ; i--) {
nums[(i - 1 + k) % nums.length] = nums[i - 1];
}
for (int i = 0; i < k; i++) {
nums[(i + k) % nums.length] = newHead[i];
}
System.out.println("轮转后的数组为:" + Arrays.toString(nums));
}
}
My second method
new新数组
思路: 创建一个新数组,把移动之后的各个元素按次序加入新数组即可。
实现:
具体代码实现:
public class Demo2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入向右轮转的位数(非负数):");
int k = sc.nextInt();
System.out.println("请输入数组的长度:");
int length = sc.nextInt();
int[] nums = new int[length];
for (int i = 0; i < nums.length; i++) {
nums[i] = sc.nextInt();
}
//copyOf复制指定的数组,使用零截断或填充(如有必要),以使副本具有指定的长度。
int[] newHead = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
newHead[(i + k) % nums.length] = nums[i];
}
System.out.println("轮转后的数组为:" + Arrays.toString(newHead));
}
}
My third method
反转
思路:
第一步:把要移动数组反转;
第二步:从k个位置分开为两个部分,分别反转;
第三步:把两部分合并即可;
实现:
具体代码实现:
public class LeetCode2 {
public static void main(String[] args) {
/*分析:
1,2,3,4,5,6,7
7 6 5 4 3 2 1反转
6 7 1 2 3 4 5分别反转两部分
6 7 1 2 3 4 5合并两部分
* */
int[] nums = {1,2,3,4,5,6,7};
int k = 2;
//多态
List<Integer> numsList1 = new ArrayList<>();
//添加数组元素到集合,反转
numsList1 = cutOutElement(0 , nums.length , numsList1 ,nums);
Collections.reverse(numsList1);
//截取第一部分,反转
List<Integer> numsList2 = new ArrayList();
numsList2 = cutOutElement(0 , k , numsList2 , numsList1);
Collections.reverse(numsList2);
//截取第二部分,反转
List<Integer> numsList3 = new ArrayList();
numsList3 = cutOutElement(k , numsList1.size() , numsList3 , numsList1);
Collections.reverse(numsList3);
//合并两部分
numsList2.addAll(numsList3);
//List<Integer>转为int[],打印输出
int[] ints = numsList2.stream().mapToInt(Integer::valueOf).toArray();
System.out.println(Arrays.toString(ints));
}
//处理两个集合
public static List<Integer> cutOutElement(int begin , int end , List<Integer> numsListResult , List<Integer> numsList){
for (int j = begin; j < end; j++) {
numsListResult.add(numsList.get(j));
}
return numsListResult;
}
//重载:处理集合和数组
public static List<Integer> cutOutElement(int begin , int end , List<Integer> numsListResult , int[] nums){
for (int j = begin; j < end; j++) {
numsListResult.add(nums[j]);
}
return numsListResult;
}
}
收获
通过该算法,复习了重载,多态,集合, List< Integer > 转 int[]等知识;只有通过不断练习,才能灵活应用知识。反转思路参考了LeetCode官方思路,巧妙的运用反转。