跳数幸存数之和(华为od机考题)

一、题目

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值