概述
双指针
- 第三天
- 第六题:删除排序链表中的重复元素 II
- 思路
- 代码
- 第七题:三数之和
- 思路
- 代码
- 第四天
- 第八题:比较含退格的字符串
- 思路
- 代码
- 第九题:区间列表的交集
- 思路
- 代码
- 第十题:盛最多水的容器
- 思路
- 代码
第三天
第六题:删除排序链表中的重复元素 II
82.删除排序链表中的重复元素 II
思路
方法一:
创建新的链表然后找旧链表中不重复的元素加入新链表中然后返回新链表
方法二:
1.创建新的链表并让它与本来的链表相连,两个指针分别指向两个链表。
2.如果head的当前结点的值不等于下一结点的值。那么让指向新链表的指针来到当前结点,这样就链接了前一结点和当前结点。然后head当前结点移至下一结点。
3.如果head当前结点值等于下一结点值。那么就让head一直往后直到当前结点值不等于下一结点value,然后再将当前结点移至下一结点。此时重复节点就过去了,然后让指向新链表的指针来到head开始新一轮的判断。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode phead = new ListNode(0);
ListNode p = phead;
while(head != null && head.next != null){
if(head.val == head.next.val){
while(head.next != null && head.val == head.next.val){
head = head.next;
}
head = head.next;
p.next = head;
}else{
p.next = head;
p = p.next;
head = head.next;
}
}
return phead.next;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode phead = new ListNode(0);
phead.next = head;
ListNode p = phead;
while(head != null && head.next != null){
if(head.val == head.next.val){
while(head.next != null && head.val == head.next.val){
head = head.next;
}
//重复元素过滤完进入下一次判断
head = head.next;
p.next = head;
}else{
//p = head在出现一次重复元素后相当于p = p.next;但如果链表开始元素不重复则使用p = p.next时第二次进入会出现空指针异常
p = head;
head = head.next;
}
}
return phead.next;
}
}
第七题:三数之和
15.三数之和
思路
1.三数之和为0,可知最小数必然小于等于0,最大数必然大于等于0,要不重复,三数之中只要有两个数不同,要满足和为0,第三数必不同。
2.对原数组进行升序排序,在元素小于等于0的情况下对第一个进行遍历,然后第三个数在元素大于等于0的情况下从数组最后对三个数进行遍历,第二个数下标应该满足大于第一个而小于第三个。
3.可知第二个数和第三个数的确定可以使用双指针。
代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums); // 对数组进行升序排序
ArrayList<List<Integer>> lists = new ArrayList<>();
for(int i = 0; i < nums.length-2 && nums[i] <= 0; i++){ //对第一个数进行遍历
if(i > 0 && nums[i] == nums[i-1]){ //去重
continue;
}
int k = nums.length - 1;
int j = i + 1;
while(j < k && nums[k] >= 0) { //使用双指针确定第二个数和第三个数下标
if(nums[i] + nums[j] + nums[k] > 0){ //三数之和大于0,减小第三个数下标
k--;
}else if(nums[i] + nums[j] + nums[k] < 0){ //三数之和小于0,增大第二个数下标
j++;
}else{
//找到满足三数之和等于0将其加入列表
ArrayList<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
lists.add(list);
//对j,k进行去重
while(j < k && nums[j] == nums[j+1]) j++;
while(j < k && nums[k] >= 0 && nums[k] == nums[k-1]) k--;
j++;
k--;
}
}
}
return lists;
}
}
第四天
第八题:比较含退格的字符串
844.比较含退格的字符串
思路
因已知最大长度,所以可以通过两个字符数组分别计算两个字符串去除退格后的值,并用两个指针记录其长度,如长度不一样则不相等,若长度一样就需要继续比较每一位的值,若出现不相等的,则说明两个字符串不相等。
代码
class Solution {
public boolean backspaceCompare(String s, String t) {
char[] S = new char[200];
char[] T = new char[200];
int Slength = 0, Tlength = 0;
char[] schars = s.toCharArray();
char[] tchars = t.toCharArray();
for(int i = 0; i < schars.length; i++){
char c = schars[i];
if(c != '#'){ //正常字符加入数组中向后移动下标
S[Slength++] = c;
}else{
if(Slength > 0) { //在退格同时保证下标的正确性
Slength--;
}
}
}
for(int i = 0; i < tchars.length; i++){
char c = tchars[i];
if(c != '#'){ //正常字符加入数组中向后移动下标
T[Tlength++] = c;
}else{
if(Tlength > 0) { //在退格同时保证下标的正确性
Tlength--;
}
}
}
if(Slength != Tlength){ // 比较长度
return false;
}else{
for(int i = 0; i < Slength; i++){ //比较每一位字符
if(S[i] != T[i]){
return false;
}
}
return true;
}
}
}
第九题:区间列表的交集
986.区间列表的交集
思路
1.两个区间只要满足L1 <= R2 和 L2 <= R1,就会存在交集。
2.当存在交集时,交集的开始就是两个区间开始值中的较大一个,交集的结尾肯定是两个区间结束值较小的一个。
3.当使用一个区间的结尾时,说明该区间所有可能和另一个列表中的区间产生的交集全部找到了,此时就可以移动指针到下一个区间。
代码
class Solution {
public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {
ArrayList<int[]> ints = new ArrayList<>();
int flength = 0, slength = 0;
while(flength < firstList.length && slength < secondList.length){
if(firstList[flength][1] < secondList[slength][0]){ //firstList在SecondList之前,无交集,移动flength
flength++;
}else if(secondList[slength][1] < firstList[flength][0]){ //secondList在firstList之前,无交集,移动slength
slength++;
}else{ //存在交集
int first, end;
//确定开始
if (firstList[flength][0] > secondList[slength][0]) {
first = firstList[flength][0];
} else {
first = secondList[slength][0];
}
//确定结尾
if (firstList[flength][1] < secondList[slength][1]) {
end = firstList[flength][1];
flength++;
} else if (firstList[flength][1] > secondList[slength][1]) {
end = secondList[slength][1];
slength++;
} else {
end = firstList[flength][1];
flength++;
slength++;
}
//加入结果
ints.add(new int[]{first,end});
}
}
//将结果列表转化为二维数组并返回
return ints.toArray(new int[0][0]);
}
}
第十题:盛最多水的容器
11.盛最多水的容器
思路
1.题目意思就是算面积,而面积就是两条高较小的一个乘以下标距离。
2.使用左右指针,其往中间靠拢时距离会减小,为了使面积可能比靠拢之前大,那么最小高度一定要增大,所以就需要移动高度较小的位置的下标,找到比它高的位置,然后再次计算面积并与之前的比较。一直进行这种操作直到两指针重合这样就可以得到最大面积。
代码
class Solution {
public int maxArea(int[] height) {
int l = 0, r = height.length-1;
int sum = 0;
while(l < r){
int h1 = height[l];
int h2 = height[r];
//判断哪条高较小
if(h1 < h2){
sum = Math.max(sum,h1 * (r - l)); //更新最大面积
while(l < r && h1 >= height[l]){ //找比其高的边
l++;
}
}else{
sum = Math.max(sum,h2 * (r - l)); //更新最大面积
while(r > l && h2 >= height[r]){ //找比其高的边
r--;
}
}
}
return sum;
}
}
最后
以上就是友好灯泡为你收集整理的力扣 (LeetCode)算法基础双指针第三天第四天的全部内容,希望文章能够帮你解决力扣 (LeetCode)算法基础双指针第三天第四天所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复