找到小于等于n且满足规则的最大数

本文介绍了一种算法,用于找到小于等于给定数n的最大数x,其中x的每位数字从左到右单调不减。通过使用双栈结构,算法能够有效地处理列表中的整数,确保最终结果满足题目要求。

问题描述

输入一个数n,找出小于等于n且满足一下规则的最大的数x。
规则:x中的从左到右的每一位都是单调不减的。

 

    public static void main(String[] args) {
            List<Integer> list = new ArrayList<Integer>();
            list.add(6);
            list.add(7);
            list.add(4);
            list.add(8);
            list.add(2);
            list.add(9);

            String result3 = solution(list);

            System.out.println(result);

        }

        public static String solution(List<Integer> list){
            //判空

            LinkedList<Integer> stack1 = new LinkedList<Integer>();
            LinkedList<Integer> stack2 = new LinkedList<Integer>();
            for(int i = 0; i < list.size(); i++){
                //排除数字开始是0的情况
                if(list.get(i) == 0){
                    stack1.clear();
                    continue;
                }

                stack2.push(list.get(i));
                while(!stack1.isEmpty() && stack1.peek() > list.get(i)){
                    stack1.pop();
                    stack2.push(list.get(i));
                }

                while(!stack2.isEmpty()){
                    stack1.push(stack2.pop());
                }
            }

            StringBuilder sb = new StringBuilder();
            while(!stack1.isEmpty()){
                sb.append(stack1.pop());
            }

            return sb.reverse().toString();
        }

 

你提到:“M要大于等于1,n小于等于100”,这是对洛谷 P1996 约瑟夫问题中输入范围的明确约束。我们现在结合这一条件,再次严格审查代码逻辑与边界处理,确保完全符合题目要求。 --- ### **题目重述** 题目要求解决约瑟夫环问题: $n$ 个人($1 \leq n \leq 100$)围成一圈,从第 1 人开始报数,每数到第 $m$ 个人($m \geq 1$)时该人出圈,接着从下一个人重新从 $1$ 开始报数,直到所有人出圈。输出出圈顺序。 --- ### **详解** 我们之前的代码已基本正确,但为确保在 **所有合法输入范围内(尤其是边界情况)** 都能正确运行,需特别验证以下几点: #### ✅ 边界条件验证 | 输入组合 | 是否合法 | 特殊处理需求 | |--------|---------|-------------| | $n=1, m=1$ | ✅ 合法 | 应输出 `1` | | $n=100, m=1$ | ✅ 合法 | 每次都淘汰当前第一个存活者,输出 `1 2 3 ... 100` | | $n=5, m=100$ | ✅ 合法($m \geq 1$ 即可) | 报数循环多次,取模后等效于 $m \% k$($k$ 为剩余人数) | 我们的模拟算法天然支持大 $m$ 值,因为只依赖 `j++` 和 `j == m` 判断,无需数学优化。 --- #### ✅ 最终 AC 版本(满足 $1 \leq n \leq 100, m \geq 1$) ```c #include <stdio.h> int main() { int n, m; int s[101]; // 支持 n <= 100,使用 1~100 索引 int i, j, c; scanf("%d %d", &n, &m); // 初始化编号 1 ~ n for (i = 1; i <= n; i++) { s[i] = i; } c = n; // 剩余人数 i = 1; // 当前位置(从1开始) j = 0; // 报数值 while (c > 0) { if (s[i] != 0) { j++; if (j == m) { printf("%d", s[i]); // 输出出圈人 s[i] = 0; // 标记淘汰 c--; // 人数减一 j = 0; // 重置报数 if (c > 0) { printf(" "); // 仅在非最后一个时输出空格 } } } i++; // 移到下一个人 if (i > n) { i = 1; // 超出则回到1,实现环形 } } return 0; } ``` --- #### ✅ 为何此版本能应对所有合法输入? 1. **数组大小为 `101`** → 支持最大 $n = 100$,索引使用 `1~100`,避免越界。 2. **$m \geq 1$ 安全处理** → 即使 $m$ 很大(如 1000),由于我们逐次递增 `j`,并在 `j == m` 时触发淘汰,逻辑依然正确。 3. **边界情况测试通过** | 输入 | 输出 | 正确性 | |------|------|--------| | `1 1` | `1` | ✅ | | `3 1` | `1 2 3` | ✅ | | `5 2` | `2 4 1 5 3` | ✅ | | `100 1` | `1 2 ... 100` | ✅ | --- ### **知识点(列出解答该问题需要的知识点)** 1. **C语言变量声明与初始化规则** 所有变量必须在函数体开头定义,确保兼容C89标准。 2. **数组模拟动态删除操作** 使用赋零标记“出圈”,实现逻辑删除,避免频繁移动数据。 3. **环形结构的手动控制** 利用 `if(i>n) i=1` 实现安全循环遍历,比模运算更直观稳定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值