DAY5-力扣刷题

devtools/2024/9/23 12:20:55/

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

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

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

方法一:递归(不好想)

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

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

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

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

class Solution {public ListNode swapPairs(ListNode head) {//递归完成的标志if(head==null||head.next==null){return head;}//假如有两个节点a,bListNode 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>=xif(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.ppmy.cn/devtools/52193.html

相关文章

【INTEL(ALTERA)】Nios® II无法使用基于 Ubuntu 18.04.5 的 WSL 进行构建

现象 在使用 Ubuntu 18.04.5 构建 WSL 的Nios II处理器时&#xff0c;任何英特尔 Quartus Prime 软件版本都可能会看到此问题。 原因 这是因为在 Nios II Command Shell 中运行命令 “wslpath -u .”时返回值不同。 正常工作&#xff1a;命令返回”。故障&#xff1a;命令返回…

Oracle VM VirtualBox虚拟机安装的 Linux系统中的虚拟机和Windows 10客户机时间不同步设置

遇到一个Oracle VM VirtualBox中间件过期&#xff0c;导致在Oracle VM VirtualBox搭建的应用启用失败。在网上找了一下&#xff0c;原因是&#xff1a;Oracle VM VirtualBox中的中间件在指定时间内才能使用&#xff0c;需要修改系统时间。 介绍我的环境&#xff0c;Windows10主…

PHP框架详解 - ThinkPHP框架

ThinkPHP 是一个开源的轻量级 PHP 开发框架&#xff0c;它遵循 Apache2 开源许可协议发布&#xff0c;适用于敏捷 WEB 应用开发和简化企业应用开发。以下是对 ThinkPHP 框架的一些基本介绍和特点&#xff1a; 轻量级&#xff1a;ThinkPHP 以其轻量级特性而闻名&#xff0c;适合…

物联网主机E6000:智慧安防的核心动力

随着科技的不断进步&#xff0c;物联网&#xff08;IoT&#xff09;技术已经深入到我们生活的各个领域&#xff0c;尤其是在智慧安防领域&#xff0c;物联网技术的应用正变得越来越广泛。物联网主机E6000作为一款高性能的智能设备&#xff0c;其在智慧安防系统中扮演着至关重要…

C# 泛型分析

1、object类型是一切类型的父类。 2、通过继承&#xff0c;子类拥有父类的一切属性和行为&#xff0c;任何父类出现的地方&#xff0c;都可以用子类来代替。 但是上面object类型的方法又会带来另外一个问题&#xff1a;装箱和拆箱&#xff0c;会损耗程序的性能。 在泛型类型…

图像处理:Python使用OpenCV进行图像锐化 (非锐化掩模、拉普拉斯滤波器)

文章目录 非锐化掩模 (Unsharp Masking)拉普拉斯滤波器 (Laplacian Filter)效果对比总结 在图像处理中&#xff0c;锐化操作用于增强图像的边缘和细节&#xff0c;使图像看起来更清晰。常见的图像锐化方法包括非锐化掩模&#xff08;Unsharp Masking&#xff09;和拉普拉斯滤波…

NLP--朴素贝叶斯

1.在很多时候&#xff0c;我们不能像抛硬币一样通过客观性的方式来得到正反面的概率&#xff0c;而是常常遇到主观性的概率时&#xff0c;我们就不得不提及贝叶斯学派。贝叶斯概率是一种对概率的解释。概率被解释为代表一种具备某种知识状态的合理预期。因此&#xff0c;贝叶斯…

使用Selenium进行元素定位的全面指南

使用Selenium进行元素定位的全面指南 引言 Selenium 是一个广泛使用的开源工具&#xff0c;用于自动化Web浏览器的操作。无论你是进行自动化测试&#xff0c;还是需要抓取网页数据&#xff0c;Selenium 都是一个非常有用的工具。而在Selenium中&#xff0c;定位网页元素是自动…