Java 第 35 课 1823. 找出游戏的获胜者 71. 简化路径

本文探讨了两种信息技术问题:一是约瑟夫环问题,通过递归和双端队列实现找到游戏的获胜者;二是简化路径问题,利用栈和队列来解析路径并返回简化后的结果。文章深入解析了算法思路,并提供了Java和Python的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1823. 找出游戏的获胜者

class Solution:
    def findTheWinner(self, n: int, k: int) -> int:
        q = deque(range(1, n + 1))
        while len(q) > 1:
            for _ in range(k - 1):
                q.append(q.popleft())
            q.popleft()
        return q[0]
class Solution {
    public int findTheWinner(int n, int k) {
        Deque<Integer> q = new ArrayDeque<>();
        for (int i = 1; i < n + 1; i++) q.offer(i);
        while (q.size() > 1){
            for (int i = 1; i < k; i++){
                q.offer(q.poll());
            }
            q.poll();
        }
        return q.peek();
    }
}

约瑟夫环

第一轮会删掉第 k 个人,问题就变为对 n - 1 个人进行这个游戏。
假设我们知道 f(n−1, k) 最终剩下的人的编号,由于我们删了第 k 个人,n − 1 个人的游戏是从原来第 k + 1 个人开始的,原来的编号和新的编号有一个偏差 k。
以坐标从 0 到 n - 1 来看的话(去掉 1 的偏差减少计算量,最终加一次 1 即可):
f(n, k) = (f(n - 1, k) + k) \ % n
当只剩一个人时,即 f(1, k) = 0
从 f(1, k) 推出 f(2, k) 一直到 f(n, k)即可。

class Solution:
    def findTheWinner(self, n: int, k: int) -> int:
        ans = 0
        for i in range(2, n + 1):
            ans = (ans + k) % i
        return ans + 1

每次往同一方向,以固定步长 k 进行消数。由于下一次操作的发起点为消除位置的下一个点(即前后两次操作发起点在原序列下标中相差 kk),同时问题规模会从 n 变为 n - 1,因此原问题答案等价于 findTheWinner(n - 1, k) + k。

一些细节,由于编号从 1 开始,在返回答案时我们需要将结果为 0 的值映射回编号 n。

class Solution {
    public int findTheWinner(int n, int k) {
        if (n <= 1) return n;
        int ans = (findTheWinner(n - 1, k) + k) % n;
        return ans == 0 ? n : ans;
    }
}

71. 简化路径

知识点: 用队列实现栈 Deque, ArrayDeque, pollLast, offer, equals, split, join.

class Solution:
    def simplifyPath(self, path: str) -> str:
        paths, q = path.split('/'), []
        for p in paths:
            if p == '..':   # ..
                if q: q.pop()
            elif p not in ".": q.append(p) # . // 
        return '/' + '/'.join(q)
class Solution {
    public String simplifyPath(String path) {
        Deque<String> stack = new LinkedList<>(); // new ArrayDeque<String>();
        for (String p : path.split("/")) {
            if ("..".equals(p)) { // 错 p == ".." 比较对象
                if (!stack.isEmpty()) stack.pollLast();
            } else if (p.length() > 0 && !".".equals(p)) {
                stack.offer(p);
            }
        }      
        // return "/" + String.join("/", stack);

        StringBuilder ans = new StringBuilder();
        while (!stack.isEmpty()) {
            ans.append('/');
            ans.append(stack.poll());
        }     
        return ans.isEmpty() ? "/" : ans.toString();
    }
}

基础知识

Queue
Deque

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值