DAY5-力扣刷题

1.两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣(LeetCode)

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

方法一:递归(不好想)

可以通过递归的方式实现两两交换链表中的节点。 

递归的终止条件是链表中没有节点,或者链表中只有一个节点,此时无法进行交换。

如果链表中至少有两个节点,则在两两交换链表中的节点之后,原始链表的头节点变成新的链表的第二个节点,原始链表的第二个节点变成新的链表的头节点。

链表中的其余节点的两两交换可以递归地实现。在对链表中的其余节点递归地两两交换之后,更新节点之间的指针关系,即可完成整个链表的两两交换。

class Solution {
    public ListNode swapPairs(ListNode head) {
        //递归完成的标志
        if(head==null||head.next==null){
            return head;
        }

        //假如有两个节点a,b
        ListNode newHead=head;
        head.next=swapPairs(newHead.next);
        newHead.next=head;
        return newHead;
    }
}

方法二:迭代 

也可以通过迭代的方式实现两两交换链表中的节点。

创建哑结点 dummyHead,令 dummyHead.next = head。令 temp 表示当前到达的节点,初始时 temp = dummyHead。每次需要交换 temp 后面的两个节点。

如果 temp 的后面没有节点或者只有一个节点,则没有更多的节点需要交换,因此结束交换。否则,获得 temp 后面的两个节点 node1 和 node2,通过更新节点的指针关系实现两两交换节点。

class Solution {
    public ListNode swapPairs(ListNode head) {
        //创建哑结点 dummyHead
        //先把哑结点添加到链表中
        ListNode dummyHead = new ListNode(0);
        dummyHead.next=head;
        ListNode temp=dummyHead;
        while(temp.next!=null&&temp.next.next!=null){
            ListNode node1=temp.next;
            ListNode node2=temp.next.next;
            temp.next=node2;
            node1.next=node2.next;
            node2.next=node1;
            temp=node1;
        }
        return dummyHead.next;
    }
}

 2.删除有序数组的重复项

26. 删除有序数组中的重复项 - 力扣(LeetCode)

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。
class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums == null || nums.length == 0){
            return 0;
        }
        int i=0;
        int j=1;
        while(j<nums.length){
            if(nums[i] == nums[j]){
                j++;
            }else{
                i++;
                nums[i]=nums[j];
                j++;
            }
        }
        return i+1;
    }
}

3.移除元素

27. 移除元素 - 力扣(LeetCode)

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k
class Solution {
    public int removeElement(int[] nums, int val) {
        int left=0;
        int right=nums.length;
        int count=0;
        while(left<right){
            if(nums[left]==val){
                nums[left]=nums[right-1];
                right--;
            }else{
                left++;
                count++;
            }
        }
        return count;
    }
}

 4.找出字符串第一个匹配的下标(重点)

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

class Solution {
    public static int strStr(String haystack, String needle) {
        int count=needle.length();
        for(int i=0;i<haystack.length()-count+1;i++){
            System.out.println(haystack.substring(i,i+count));
            if(haystack.substring(i,i+count).equals(needle)){
                return i;
            }
        }
        return -1;
    }
}

但我们可以看出此时所费的时间很长

考虑另一种经典的算法

方法一:Knuth-Morris-Pratt 算法(经典的字符串匹配)

快速的从主串中找到相同串

KMP算法-超细超全讲解(上)原理篇_哔哩哔哩_bilibili(详细)

class Solution {
    public int strStr(String haystack, String needle) {
        int n = haystack.length(), m = needle.length();
        if (m == 0) {
            return 0;
        }
        int[] pi = new int[m];
        for (int i = 1, j = 0; i < m; i++) {
            while (j > 0 && needle.charAt(i) != needle.charAt(j)) {
                j = pi[j - 1];
            }
            if (needle.charAt(i) == needle.charAt(j)) {
                j++;
            }
            pi[i] = j;
        }
        for (int i = 0, j = 0; i < n; i++) {
            while (j > 0 && haystack.charAt(i) != needle.charAt(j)) {
                j = pi[j - 1];
            }
            if (haystack.charAt(i) == needle.charAt(j)) {
                j++;
            }
            if (j == m) {
                return i - m + 1;
            }
        }
        return -1;
    }
}

5.两数相除(重点)

29. 两数相除 - 力扣(LeetCode)

方法一:二分法

不用除法求解中位数的方法

class Solution {
    public int divide(int dividend, int divisor) {
        //考虑被除数作为最小值的情况
        if(dividend==Integer.MIN_VALUE){
            //divisor为除数
            if(divisor==1){
                return Integer.MIN_VALUE;
            }
            if(divisor==-1){
                return Integer.MAX_VALUE;
            }
        }
        //考虑除数为最小值(此时绝对值最大)的情况
        if(divisor==Integer.MIN_VALUE){
            return dividend==divisor?1:0;
        }
        //考虑被除数为0的情况
        //被除数➗除数
        if(dividend==0){
            return 0;
        }

        //上面是特殊情况
        //后续我们只需要考虑一般情况
        //一般情况,使用二分查找
        //将所有的正数取相反数,这样就只用考虑一种情况
        boolean rev=false;
        if(dividend>0){
            dividend=-dividend;
            rev=!rev;
        }
        if(divisor>0){
            divisor=-divisor;
            rev=!rev;
        }
        int left=1,right=Integer.MAX_VALUE,ans=0;
        while(left<=right){
            //注意溢出
            //不能使用除法
            int mid=left+(right-left)>>1;
            boolean check=quickAdd(divisor,mid,dividend);
            if(check){
                ans=mid;
                //注意溢出
                if(mid==Integer.MAX_VALUE){
                    break;
                }
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return rev?-ans:ans;
        //rev本身是false
        //如果没改变,就证明原先就是俩负数,所得的结果是大于0
        //改变任意一个,结果都是负数,即true的时候,结果为-ans
    }
    //上述特殊情况
    //X和Y都是负数
    //根据除法以及余数的定义
    //1.我们首先直到暴力求解
    //X/Y可以进行分解
    //X-Y>Y,COUNT++
    //直到X-Y<Y时才证明除完了
    //我们将上述思想改成乘法的等价形式
    //Z*Y>=X>(Z+1)*Y
    //因此我们可以使用二分法得到Z,找出最大的Z使得上述不等式成立
    //快速乘
    public boolean quickAdd(int y,int z,int x){
        //x和y是负数,z是正数
        //被除数X➗除数Y
        //Z*X>=X是否成立
        int result=0,add=y;//y是除数
        while(z!=0){
            if((z&1)!=0){
                
                //需要保证result+add>=x
                //result<x-add意味着我们后续要把left,mid,right的范围画在原先的后部分
                //0<10-5
                //这就意味着前部分是不行的
                if(result<x-add){
                    return false;
                }
                result=result+add;
            }
            if(z!=1){
                //需要保证add+add>=x
                if(add<x-add){
                    return false;
                }
                add+=add;
            }
            //不能使用除法
            //二分法,求z的中间值
            z=z>>1;
        }
        return true;
        //true的时候,我们所对应的范围是原来范围的前部分
    }
    
}

方法二:类二分法

class Solution {
    public int divide(int dividend, int divisor) {
        // 考虑被除数为最小值的情况
        if (dividend == Integer.MIN_VALUE) {
            if (divisor == 1) {
                return Integer.MIN_VALUE;
            }
            if (divisor == -1) {
                return Integer.MAX_VALUE;
            }
        }
        // 考虑除数为最小值的情况
        if (divisor == Integer.MIN_VALUE) {
            return dividend == Integer.MIN_VALUE ? 1 : 0;
        }
        // 考虑被除数为 0 的情况
        if (dividend == 0) {
            return 0;
        }
        
        // 一般情况,使用类二分查找
        // 将所有的正数取相反数,这样就只需要考虑一种情况
        boolean rev = false;
        if (dividend > 0) {
            dividend = -dividend;
            rev = !rev;
        }
        if (divisor > 0) {
            divisor = -divisor;
            rev = !rev;
        }

        List<Integer> candidates = new ArrayList<Integer>();
        candidates.add(divisor);
        int index = 0;
        // 注意溢出
        while (candidates.get(index) >= dividend - candidates.get(index)) {
            candidates.add(candidates.get(index) + candidates.get(index));
            ++index;
        }
        int ans = 0;
        for (int i = candidates.size() - 1; i >= 0; --i) {
            if (candidates.get(i) >= dividend) {
                ans += 1 << i;
                dividend -= candidates.get(i);
            }
        }

        return rev ? -ans : ans;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/716103.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes新手必看:快速生成YAML清单的终极指南!

在这篇文章中&#xff0c;你将学习到几种快速创建Kubernetes YAML清单的方法&#xff0c;这些方法可以帮助你在Kubernetes中测试和部署应用程序。这些技巧同样适用于Kubernetes认证考试。 在使用Kubernetes时&#xff0c;我们经常需要搜索Kubernetes YAML文件以便部署测试Pod、…

编写一个简单的Mybatis插件

1.编写一个类&#xff0c;实现Intercepter这个接口 2.完成这个类的方法&#xff0c;并通过注解Intercepts来告诉Mybatis这个插件拦截哪个类和哪个方法 3.在Mybatis的全局配置文件里注册这个插件&#xff0c;让插件生效 4.玩一个实际功能的插件

家庭智能助手:Kompas AI引领家居智能化新纪元

一、引言 在数字化浪潮的推动下&#xff0c;现代家庭生活正迅速向智能化转型。从简单的自动化设备到复杂的智能家居系统&#xff0c;智能技术正悄无声息地改变我们的日常生活。Kompas AI作为一款前沿的家庭智能助手&#xff0c;不仅预示着家庭生活的未来趋势&#xff0c;更以其…

每日一练:攻防世界:ewm

这道题我尝试了使用montagegaps解题&#xff0c;但是没有解出来&#xff0c;图片数量不是很多&#xff0c;可以尝试用PS直接拼图&#xff0c;但是这样学不到东西&#xff0c;我也就没尝试&#xff0c;直接看的官方WP 这段代码应该是改变工作目录到small&#xff0c;并且变量当…

Sping源码(九)—— Bean的初始化(非懒加载)— Bean的创建方式(自定义BeanPostProcessor)

序言 之前文章有介绍采用FactoryBean的方式创建对象&#xff0c;以及使用反射创建对象。 这篇文章继续介绍Spring中创建Bean的形式之一——自定义BeanPostProcessor。 之前在介绍BeanPostProcessor的文章中有提到&#xff0c;BeanPostProcessor接口的实现中有一个Instantiatio…

Tensorflow-GPU工具包了解和详细安装方法

目录 基础知识信息了解 显卡算力 CUDA兼容 Tensorflow gpu安装 CUDA/cuDNN匹配和下载 查看Conda driver的版本 下载CUDA工具包 查看对应cuDNN版本 下载cuDNN加速库 CUDA/cuDNN安装 CUDA安装方法 cuDNN加速库安装 配置CUDA/cuDNN环境变量 配置环境变量 核验是否安…

【乐吾乐2D可视化组态编辑器】导航

支持点击图元&#xff0c;切换画面或跳转链接。 乐吾乐2D可视化组态编辑器地址&#xff1a;https://2d.le5le.com/ 切换画面 1. 添加事件 2. 设置事件行为 事件行为"发送消息"&#xff0c;消息名选择"导航"。 3. 配置消息参数 消息参数&#xff0c;…

图像的对比度和亮度

目标 访问像素值用0来初始化矩阵cv::saturate_cast像素转换提高一张图像的亮度 原理 图像处理 图像变换可以被视作两个步骤&#xff1a; 点操纵&#xff08;像素转换&#xff09;相邻区域转换&#xff08;以面积为基础&#xff09; 像素转换 在这种图像处理的转换过程中…

操作系统 - 进程的控制(创建与终止)

进程控制 文章目录 进程控制进程创建进程的终止wait()和waitpd()僵尸进程孤儿进程 进程创建 程序在执行的过程中&#xff0c;可能会创建多个进程&#xff0c;创建进程称为父进程&#xff0c;新的进程称为子进程&#xff0c;每个新的进程也可以创建其他进程&#xff0c;从而形成…

LinkedHashMap详解

目录 LinkedHashMap详解1、LinkedHashMap的继承体系2、LinkedHashMap的特性介绍和代码示例①、特性②、适用场景使用LinkedHashMap 实现最简单的 LRU缓存 3、LinkedHashMap的构造函数4、LinkedHashMap是如何存储元素的&#xff0c;底层数据结构是什么&#xff1f;LinkedHashMap…

功能强大的多功能文档转换工具Neevia Document Converter Pro 7.5.0.241

Neevia Document Converter Pro是一款功能强大的Windows软件,旨在将文档转换为各种格式,包括PDF、TIFF、JPEG和许多其他格式。该程序专为在企业环境中使用而设计,提供文档转换和处理过程的自动化,这使其成为处理大量文档的组织的***工具。 Neevia Document Converter Pro的…

基于Quartus Prime18.1的安装与FPGA的基础仿真(联合Modelsim)教程

Quartus是一种美国科技公司Intel&#xff08;英特尔&#xff09;公司开发的FPGA&#xff08;现场可编辑门阵列&#xff09;设计编译软件&#xff0c;用作设计、仿真、综合和布局、支持多种编程语言&#xff0c;包括VHDL、Verilog等&#xff0c;并具有丰富的功能和工具库&#x…

游戏中插入音效

一、背景音乐 准备&#xff1a;素材音乐 方法&#xff1a; 1、方法1&#xff1a; (1) 将背景音乐 bgAudio 拖放到Hierarchy面板 (2) 选中 bgAudio&#xff0c;勾选开始运行就播放、循环播放。调节音量&#xff08;volume) 2、方法2&#xff1a; (1) Create Empty&#x…

日志通关(一)

转载&#xff1a;https://mp.weixin.qq.com/s/eIiu08fVk194E0BgGL5gow 一、 日志体系 日志发展到今天&#xff0c;被抽象成了三层&#xff1a;接口层、实现层、适配层&#xff1a; 接口层&#xff1a;或者叫日志门面&#xff08;facade&#xff09;&#xff0c;就是interfa…

Aspice介绍——测试流程

文章目录 ASPICE简介一、V字模型的示意二、测试领域2.1 SWE.6&#xff1a;软件合格性测试过程目的过程成果基本实践&#xff08;BP&#xff09; 2.2 SYS.4:系统集成和集成测试过程目的过程成果基本实践&#xff08;BP&#xff09; 2.3 SYS.5&#xff1a;系统合格性测试过程目的…

【linux网络(四)】传输层协议详解(上)

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux网络 1. 前言2. UDP协议…

备忘录怎么插入文件和附件 备忘录插入文件附件方法

在繁忙的工作与生活中&#xff0c;我们时常需要记录各种信息&#xff0c;而备忘录则成为了我们不可或缺的得力助手。然而&#xff0c;当备忘录中需要包含的文件或附件越来越多时&#xff0c;如何高效、便捷地管理这些文件&#xff0c;便成为了一个亟待解决的问题。 想象一下&a…

深入剖析 Laravel 框架:构建高效PHP应用的最佳实践

引言 随着互联网的高速发展&#xff0c;PHP 作为一门广泛使用的服务器端脚本语言&#xff0c;始终备受开发者青睐。而在众多 PHP 框架中&#xff0c;Laravel 凭借其优雅的设计和高效率&#xff0c;成为了构建现代 Web 应用的热门选择。本文将从零开始&#xff0c;探讨如何使用 …

arcgis portal安装教程(含ECP授权文件)

本文介绍Portal 在windows环境下的安装部署过程&#xff0c;为了顺利进行Portal的安装&#xff0c;建议安装环境是windows server 2016。所以在操作之前首先保证有符合条件的安装机器或虚拟机&#xff0c;安装环境的存储空间建议不低于100G。 安装环境及软件 1、环境&#xff…

o.upload.addEventListener is not a function

o.upload.addEventListener is not a function 在本地的开发环境是可以正常上传的&#xff0c;但是到测试环境&#xff0c;上传就报了这么一个错 在网上寻找的方法 一、 在 node_modules/mockjs/dist/mock.js 第8308行 和 node_modules/mockjs/src/xhr/xhr.js 第216行 添加…
最新文章