首页 > 其他分享 >leetcode题目总结

leetcode题目总结

时间:2024-07-30 18:28:39浏览次数:12  
标签:总结 head 题目 删除 int arr 移除 序列 leetcode

前言

本文为leetcode上的题目简单分析总结,仅作记录,欢迎提出建议,共同学习交流。 


390.消除游戏

列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:

  • 从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
  • 重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。
  • 不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。

给你整数 n ,返回 arr 最后剩下的数字。

示例 1:

输入:n = 9
输出:6
解释:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = [2, 4, 6, 8]
arr = [2, 6]
arr = [6]

示例 2:

输入:n = 1
输出:1

分析

方法一

先创建一个动态数组List,对其中部分元素进行循环删除,num为奇数时表示正向从左到右删除,当到达最右端时反转数组,达到再次从左向右删除的效果。当list中只剩下一个元素时,利用get方法进行返回。

此方法大量的运用remove方法,删除元素。Arraylist会有大量的数据移动,所以时间复杂度较高。

class Solution {
    public int lastRemaining(int n) {
        ArrayList<Integer> list = new ArrayList<>();
        for(int i=0; i<n; i++){
            list.add(i+1);
        }
        // 表示删除第几轮
        int num=0;
        while(true){
            num++;
            // 从左往右
            if(num%2==1){
                // 删除时数在往左挪,下标在减一所以,i只需+1
                for(int i=0;i<list.size();i++){
                    if(list.size()==1){return list.get(0);}
                    list.remove(i);
                }
            }
            // 反转数组
            else{
                Collections.reverse(list);
            }
        }
    }
}

方法二

每个回合更新和记录head变量,当数组元素个数变为1时,head就是最后的一个数

什么时候更新这个head变量呢?

  1. 当我们从左边开始移除的时
  2. 当我们从右边开始移除并且剩余的数的总数 number % 2 == 1时

比如 2 4 6 8 10,我们从10开始移除,我们将会移除10,6,2,head被移除并且变为4
比如 2 4 6 8 10 12,我们从12开始移除,我们将会移除12,8,4,head仍然是2

class Solution {
    public int lastRemaining(int n) {
        int head = 1;
        // step用来表示head移动步长
        int step = 1;
        // left用来判断是从左边开始移除还是从右边开始移除(true表示从左边开始)
        boolean left = true;
        while (n > 1) {
            //从左边开始移除 or(从右边开始移除,数列总数为奇数)
            if (left || n % 2 != 0) {
                head += step;
            }
            step *= 2; //步长 * 2
            left = !left; //取反移除方向
            n /= 2; //总数 / 2
        }
        return head;
    }
}

方法三

约瑟夫环
与求解约瑟夫环类似,本题也可以通常找规律,分析出公式之后进行递推求解。

对于本题,定义 f[i] 为在 连续序列 [1,i] 中进行「起始先从左到右,再从右往左」的轮流换向间隔删除,最终左边剩余的编号;定义g[i]为在 连续序列 [1,i] 中进行「起始先从右到左,再从左往右」的轮流换向间隔删除,最终右边剩余的编号。

由于「从左往右」和「从右往左」分别为「从左端点发起,间隔删除」和「从右端点发起,间隔删除」,因此整个删除过程在连续序列中 [1,i] 中具有对称性,两者最终剩余的编号在连续序列中也具有对称性。

即可得出第一个公式:

f[i]+g[i]=i+1

由于我们对 f[i] 和 g[i] 的定义都是「连续序列」,因此如果我们希望使用 f[i] 和 g[i]  得出最终答案,我们需要在每次消除后对序列进行「重新编号」,确保能够使用 f[i] 和 g[i] 作为合法状态值,在计算出「重新编号」后的,需要将答案(编号)映射回去重新编号前的值。

起始时,我们对连续序列 [1,2,3,...,i] 执行了一次「从左往右」的消除之后,得到的序列为 [2,4,6,...,x](其中 x 根据 i 的奇偶性不同,可能为 i 或 i−1)。新序列的长度为 i/2,考虑对得到的序列进行重新编号,使其继续保有「连续序列」的定义,即变为 [1,2,3,...,⌊ ,然后执行「从右往左」的间隔删除,最终得到 之后考虑将答案编号映射回「重新编号」前的值。

此时可得到第二个公式:

f[i] = g[i/2] * 2

通过上述两个公式,我们可以将 f′[i] 进行消除,得到最终的 f[i] 关系式:

f[i] = 2 ∗ (i/2 + 1 − g[i/2])

我们知道需要实现的函数 lastRemaining 其实就是 f[i],因此该递推过程我们可以使用递归进行实现(注意的出口条件 f[1]=1)。

class Solution {
    public int lastRemaining(int n) {
        if(n == 1) return 1;
        else return 2 * (n / 2 + 1 - lastRemaining(n / 2));
    }
}

标签:总结,head,题目,删除,int,arr,移除,序列,leetcode
From: https://blog.csdn.net/2301_80395772/article/details/140781058

相关文章

  • Python 字节串转Hex字符串(一个久远的问题点总结)
    时间:2024.07.30作者:Yuan  这是一个今天看来似乎有点久远的问题,但是值得被记录和澄清一下!  那是在2022年1月份参与的一个项目中遇到的问题,大概需求是利用SHT40-AD1B-R2芯片,读取环境温度。其实就是通过i2c与这个温度传感器建立通讯,然后读取温湿度信息,对于上位机的......
  • 嵌入式必备知识总结(一)
    计算机系统结构    计算机系统结构是计算机科学中的一个重要领域,研究计算机系统的设计和组织。计算机系统结构主要关注以下几个方面:1.计算机硬件组成a.中央处理单元(CPU)CPU是计算机的核心,负责执行指令并控制其他硬件组件。算术逻辑单元(ALU):执行算术和逻......
  • 7.30第三周周二学习总结
    1vj团队5补题(上午)https://vjudge.net/contest/643995题解2cfr950(下午)https://vjudge.net/contest/643996#google_vignette最大公约数非递减序列重点1.思维:删去一个ai时,需要删除ai与前后的公因数,并加上ai-1与ai+1的最大公因数。3cf团队赛6补题(下午)思维转化题意:n个......
  • LeetCode15 三数之和
    前言题目:15.三数之和文档:代码随想录——三数之和编程语言:C++解题状态:没思路…思路不可包含重复三元组的条件是本题最大的难点,本题的一大思路在与排序后进行去重。代码双指针法classSolution{public:vector<vector<int>>threeSum(vector<int>&nums......
  • git简单使用总结
    概述Git是一种分布式版本控制系统。要想深刻理解Git的工作原理,需要理解理解Git的三个存放区域:本地工作目录、暂存区和仓库,也可以称为三棵树,不过在仓库这个地方又可以分为本地仓库和远程仓库。WorkingDirectory:本地工作目录(工作区)Stage(Index):暂存区Reposi......
  • 亏钱、踩坑总结的经验之:合伙开宵夜档口!
    亏钱、踩坑总结的经验之:合伙开宵夜档口!今年上半年开了一间宵夜档,是跟以前同事三个人合伙的,开之前说的好听的不得了,分工明确,做哪些产品要怎么怎么做利润高的能赚钱的,一切都想象的很美好,感觉今年肯定要发财,汽车之家每天都看好几遍。结果一开工,说好六点开工,每天两个人八点还没来......
  • lca总结+树上差分
    lcalca简称最近公共祖先——简介在此,不过多赘述这里主要写的是倍增算法,oi-wiki上用的是vector,由于本人不会,只会用链表,所以这里就放链表的代码了例题加一个数组按倍增数组的方式存距离即可题解——点击查看代码#include<bits/stdc++.h>#defineintlonglongconstint......
  • MYSQL学习总结
    事务:一个不可拆分的操作,要么全部执行完,要么全都不执行;隔离级别:总共有四个,分别是ReadUncommitted(读取未提交内容),ReadCommitted(读取提交内容),RepeatableRead(可重读),Serializable(可串行化);ReadUncommitted(读取未提交内容):一个事务可以读取另一个事务未提交的数据;如果另一个事务......
  • 7月30日考试总结
    7月30日考试总结T1报数游戏II要点:将试子列出来后,不难发现求前缀和找最小负数即可。问题:无。反思:一眼前缀和没啥好说的。T2百万富翁的第二次实验要点:做一下前缀和或离散化,然后双指针即可。问题:考试时写了个dp,以为时间复杂度是能给很多分的,结果就给了特判分主要是数据全......
  • LeetCode-day30-2961. 双模幂运算
    LeetCode-day30-2961.双模幂运算题目描述示例示例1:示例2:思路代码题目描述给你一个下标从0开始的二维数组variables,其中variables[i]=[ai,bi,ci,mi],以及一个整数target。如果满足以下公式,则下标i是好下标:0<=i<variables.length((aibi%10)ci)......