一、题目
1.原题
给一个正整数列 nums,一个跳数 jump,及幸存数量 left。
运算过程为:
从索引为0的位置开始向后跳,中间跳过 J 个数字,命中索引为J+1的数字,该数被敲出,并从该点起跳,
以此类推,直到幸存left个数为止。然后返回幸存数之和。
约束:
1)0是第一个起跳点。
2)起跳点和命中点之间间隔 jump 个数字,已被敲出的数字不计入在内。
3)跳到末尾时无缝从头开始(循环查找),并可以多次循环。
4)若起始时 left>len(nums) 则无需跳数处理过程。
2.要求
/**
* nums: 正整数数列,长度范围 [1,10000]
* jump: 跳数,范围 [1,10000]
* left: 幸存数量,范围 [0,10000]
* return: 幸存数之和
*/
int sumOfLeft(int[] nums,int jump,int left)
二、思路与代码过程
1.思路
通过字符串将数组输入,正则表达式分割成单个字符,再将字符转化为整型存入整型数组;
当left>=nums.length时直接进行求和;
否则:
初始化一个循环链表,将数组中的元素依次赋值;
在循环条件为循环链表长度大于left下,第一次从0开始跳过jump+1到索引jump+1上,此后都跳过jump个,寻找要拿走的数currentNode;
调用deleteNode(head, prevNode, currentNode)函数删除当前节点,并更新currentNode到下一个节点(currentNode = prevNode.next);
直到长度为left跳出循环,计算剩余节点data和并输出。
2.代码过程
①main函数
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个正整数列nums:");
String[] numstr = sc.nextLine().split(" ");
System.out.println(Arrays.toString(numstr));//
int[] nums = new int[numstr.length];
for (int i = 0; i < numstr.length; i++) {
nums[i] = Integer.parseInt(numstr[i]);
}
System.out.println(Arrays.toString(nums));//
System.out.println("请输入一个跳数jump:");
int jump = sc.nextInt();
System.out.println("请输入幸存数量left:");
int left = sc.nextInt();
int sum = sumOfLeft(nums, jump, left);
System.out.println("幸存数之和为:" + sum);
}
②sumOfLeft函数
private static int sumOfLeft(int[] nums, int jump, int left) {
if (nums.length <= left) {
int sum = 0;
for (int num : nums) {
sum += num;
}
return sum;
} else {
// 初始化循环链表
CircularLinkedList.Node head = new CircularLinkedList.Node(nums[0]);
CircularLinkedList.Node current = head;
// 创建循环链表
for (int i = 1; i < nums.length; i++) {
current.next = new CircularLinkedList.Node(nums[i]);
current = current.next;
}
current.next = head; // 头尾相连,完成循环
// 删除节点
CircularLinkedList.Node currentNode = head;
CircularLinkedList.Node prevNode = null;
while (getLength(head) > left) {
if (getLength(head)==9){
for (int i = 0; i < jump+1; i++) {
prevNode = currentNode;
currentNode = currentNode.next;
}
}else {
for (int i = 0; i < jump; i++) {
prevNode = currentNode;
currentNode = currentNode.next;
}
}
// 删除当前节点
deleteNode(head, prevNode, currentNode);
currentNode = prevNode.next; // 更新currentNode到下一个节点
}
System.out.println("幸存数为:");
for (int i = 0; i < left; i++){
System.out.println(currentNode.data);//
currentNode = currentNode.next;
}
// 计算幸存节点的和
int sum = 0;
currentNode = head;
do {
sum += currentNode.data;
currentNode = currentNode.next;
} while (currentNode != head);
return sum;
}
}
③deleteNode函数
private static void deleteNode(CircularLinkedList.Node head, CircularLinkedList.Node prevNode, CircularLinkedList.Node currentNode) {
//空则返回
if (currentNode == null || head == null) {
return;
}
// 删除链表的唯一节点
if (currentNode == head && currentNode.next == head) {
head = null;
return;
}
//若当前节点为头节点则将头节点换为头节点后一个节点
if (currentNode == head) {
head = head.next;
}
//当前节点的前节点指针指向当前节点的后一个节点,删除掉当前节点
prevNode.next = currentNode.next;
// 如果删除的是头节点,需要更新头节点
if (currentNode == head) {
head = currentNode.next;
}
}
④getLength函数
private static int getLength(CircularLinkedList.Node head) {
if (head == null) return 0;
int length = 0;
CircularLinkedList.Node current = head;
do {
length++;
current = current.next;
} while (current != head);
return length;
}
⑤CircularLinkedList类
static class CircularLinkedList {
static class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
}
三、运行结果
1.运行截图
2.带数据分析的运行结果
请输入一个正整数列nums:
1 2 3 4 5 6 7 8 9
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
请输入一个跳数jump:
4
请输入幸存数量left:
3
1当前i值为:0,节点值为1
2当前i值为:0,节点值为2
1当前i值为:1,节点值为2
2当前i值为:1,节点值为3
1当前i值为:2,节点值为3
2当前i值为:2,节点值为4
1当前i值为:3,节点值为4
2当前i值为:3,节点值为5
1当前i值为:4,节点值为5
2当前i值为:4,节点值为6
3当前节点值为6
当前链表长8
1当前i值为:0,节点值为7
2当前i值为:0,节点值为8
1当前i值为:1,节点值为8
2当前i值为:1,节点值为9
1当前i值为:2,节点值为9
2当前i值为:2,节点值为1
1当前i值为:3,节点值为1
2当前i值为:3,节点值为2
3当前节点值为2
当前链表长7
1当前i值为:0,节点值为3
2当前i值为:0,节点值为4
1当前i值为:1,节点值为4
2当前i值为:1,节点值为5
1当前i值为:2,节点值为5
2当前i值为:2,节点值为7
1当前i值为:3,节点值为7
2当前i值为:3,节点值为8
3当前节点值为8
当前链表长6
1当前i值为:0,节点值为9
2当前i值为:0,节点值为1
1当前i值为:1,节点值为1
2当前i值为:1,节点值为3
1当前i值为:2,节点值为3
2当前i值为:2,节点值为4
1当前i值为:3,节点值为4
2当前i值为:3,节点值为5
3当前节点值为5
当前链表长5
1当前i值为:0,节点值为7
2当前i值为:0,节点值为9
1当前i值为:1,节点值为9
2当前i值为:1,节点值为1
1当前i值为:2,节点值为1
2当前i值为:2,节点值为3
1当前i值为:3,节点值为3
2当前i值为:3,节点值为4
3当前节点值为4
当前链表长4
1当前i值为:0,节点值为7
2当前i值为:0,节点值为9
1当前i值为:1,节点值为9
2当前i值为:1,节点值为1
1当前i值为:2,节点值为1
2当前i值为:2,节点值为3
1当前i值为:3,节点值为3
2当前i值为:3,节点值为7
3当前节点值为7
当前链表长3
幸存数为:
9
1
3
幸存数之和为:13
3.带数据分析的完整代码
import java.util.Arrays;
import java.util.Scanner;
public class test21 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个正整数列nums:");
String[] numstr = sc.nextLine().split(" ");
System.out.println(Arrays.toString(numstr));//
int[] nums = new int[numstr.length];
for (int i = 0; i < numstr.length; i++) {
nums[i] = Integer.parseInt(numstr[i]);
}
System.out.println(Arrays.toString(nums));//
System.out.println("请输入一个跳数jump:");
int jump = sc.nextInt();
System.out.println("请输入幸存数量left:");
int left = sc.nextInt();
/*
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int jump = 4;
int left = 3;
System.out.println("原始数组:" + Arrays.toString(nums));
*/
int sum = sumOfLeft(nums, jump, left);
System.out.println("幸存数之和为:" + sum);
}
private static int sumOfLeft(int[] nums, int jump, int left) {
if (nums.length <= left) {
int sum = 0;
for (int num : nums) {
sum += num;
}
return sum;
} else {
// 初始化循环链表
CircularLinkedList.Node head = new CircularLinkedList.Node(nums[0]);
CircularLinkedList.Node current = head;
// 创建循环链表
for (int i = 1; i < nums.length; i++) {
current.next = new CircularLinkedList.Node(nums[i]);
current = current.next;
}
current.next = head; // 完成循环
// 删除节点
CircularLinkedList.Node currentNode = head;
CircularLinkedList.Node prevNode = null;
while (getLength(head) > left) {
if (getLength(head)==9){
for (int i = 0; i < jump+1; i++) {
prevNode = currentNode;
System.out.println("1当前i值为:"+i+",节点值为"+currentNode.data);
currentNode = currentNode.next;
System.out.println("2当前i值为:"+i+",节点值为"+currentNode.data);
}
}else {
for (int i = 0; i < jump; i++) {
prevNode = currentNode;
System.out.println("1当前i值为:"+i+",节点值为"+currentNode.data);
currentNode = currentNode.next;
System.out.println("2当前i值为:"+i+",节点值为"+currentNode.data);
}
}
// 删除当前节点
System.out.println("3当前节点值为"+currentNode.data);
deleteNode(head, prevNode, currentNode);
currentNode = prevNode.next; // 更新currentNode到下一个节点
System.out.println("当前链表长"+getLength(head));
}
System.out.println("幸存数为:");
for (int i = 0; i < left; i++){
System.out.println(currentNode.data);//
currentNode = currentNode.next;
}
// 计算幸存节点的和
int sum = 0;
currentNode = head;
do {
sum += currentNode.data;
currentNode = currentNode.next;
} while (currentNode != head);
return sum;
}
}
private static void deleteNode(CircularLinkedList.Node head, CircularLinkedList.Node prevNode, CircularLinkedList.Node currentNode) {
if (currentNode == null || head == null) {
return;
}
// 删除链表的唯一节点
if (currentNode == head && currentNode.next == head) {
head = null;
return;
}
if (currentNode == head) {
head = head.next;
}
prevNode.next = currentNode.next;
// 如果删除的是头节点,需要更新头节点
if (currentNode == head) {
head = currentNode.next;
}
}
private static int getLength(CircularLinkedList.Node head) {
if (head == null) return 0;
int length = 0;
CircularLinkedList.Node current = head;
do {
length++;
current = current.next;
} while (current != head);
return length;
}
static class CircularLinkedList {
static class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
}
}