【Leetcode训练】算法入门——双指针全刷

目录

977. 有序数组的平方——简单

题目描述

img

题解

方法一:直接排序

class Solution {
    
    
    public int[] sortedSquares(int[] nums) {
    
    
        for (int i = 0; i < nums.length; i++) {
    
    
			nums[i] = nums[i]*nums[i];
		}
		Arrays.sort(nums);
        return nums;
    }
}

复杂度分析

  • 时间复杂度:O(nlogn),其中 nn 是数组 nums 的长度。
  • 空间复杂度:O(logn)。除了存储答案的数组以外,我们需要 O(logn) 的栈空间进行排序。

方法二:双指针

img

class Solution {
    
    
    public int[] sortedSquares(int[] nums) {
    
    
        int arr[] = new int [nums.length];
		for (int i = 0,j=nums.length-1,k=nums.length-1;i<=j;) {
    
    
			if (nums[i]*nums[i]>nums[j]*nums[j]) {
    
    
				arr[k]=nums[i]*nums[i];
				i++;
			}
			else {
    
    
				arr[k]=nums[j]*nums[j];
				j--;
			}
			k--;
		}
        return arr;
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组nums 的长度。
  • 空间复杂度:O(1)。除了存储答案的数组以外,我们只需要维护常量空间。

189. 轮转数组——中等

题目描述

img

题解

方法一:使用额外的数组

我们可以使用额外的数组来将每个元素放至正确的位置。用 nn 表示数组的长度,我们遍历原数组,将原数组下标为 i 的元素放至新数组下标为 (i+k)mod n 的位置,最后将新数组拷贝至原数组即可。

class Solution {
    
    
    public void rotate(int[] nums, int k) {
    
    
        int n = nums.length;
        int[] newArr = new int[n];
        for (int i = 0; i < n; ++i) {
    
    
            newArr[(i + k) % n] = nums[i];
        }
        System.arraycopy(newArr, 0, nums, 0, n);
    }
}

复杂度分析

  • 时间复杂度: O(n),其中 nn 为数组的长度。
  • 空间复杂度: O(n)。

方法二:

将原数组从后往前的k个数取出,放入新数组,再将原数组的剩余前面的数取出放入新数组后面

class Solution {
    
    
    public void rotate(int[] nums, int k) {
    
    
        int arr[]=new int[nums.length];
		if(k>nums.length) {
    
    
			k=k%nums.length;
		}
		for (int i = nums.length-k,j=0; i < nums.length; i++) {
    
    
			arr[j]=nums[i];
			j++;
		}
		for (int i = 0,j=k; i <nums.length-k;) {
    
    
			arr[j]= nums[i];
			++i;
			j++;
		}
//		for (int i : arr) {
    
    
//			System.out.println(i);
//		}
		
		System.arraycopy(arr, 0, nums, 0, nums.length);
    }
}

283. 移动零——简单

题目描述

img

题解

方法一:

//思路:设置一个index,表示非0数的个数,循环遍历数组,
// 如果不是0,将非0值移动到第index位置,然后index + 1
//遍历结束之后,index值表示为非0的个数,再次遍历,从index位置后的位置此时都应该为0
class Solution {
    
    
    public void moveZeroes(int[] nums) {
    
    
        		int index=0;
		for (int i = 0; i < nums.length; i++) {
    
    
			if (nums[i]!=0) {
    
    
				nums[index]=nums[i];
				index++;
			}
		}
		for (int i = index; i < nums.length; i++) {
    
    
			nums[index] = 0;
			index++;
		}
    }
}

方法二:双指针

img

class Solution {
    
    
    public void moveZeroes(int[] nums) {
    
    
        int left = 0;
    	int right =0;
    	while (right<nums.length) {
    
    
			if (nums[right]!=0) {
    
    
				swap(nums, left, right);
				left++;
			}
			right++;
		}
    }
    public void swap(int nums[],int left,int right) {
    
    
    	int temp = nums[left];
    	nums[left] = nums[right];
    	nums[right] = temp;
    }
    
}

复杂度分析

img


167. 两数之和 II - 输入有序数组——简单

题目描述

img

题解

方法一:双指针

img

class Solution {
    
    
    public int[] twoSum(int[] numbers, int target) {
    
    
//    	int arr [] = new int [2];
    	int left = 0;
    	int right = numbers.length-1;
    	while (left<right) {
    
    
    		if (numbers[left]+numbers[right]==target) {
    
    
    			return new int[] {
    
    left+1,right+1};
			}else if (numbers[left]+numbers[right]<target) {
    
    
				left++;
			}else {
    
    
				right--;
			}
		}   	
    	return new int[0];
    }
}

复杂度分析

img

方法二:二分查找

img

class Solution {
    
    
    public int[] twoSum(int[] numbers, int target) {
    
    
//    	int arr[] = new int [2];
    	for (int i = 0; i < numbers.length; i++) {
    
    
			int low = i+1;
			int high = numbers.length-1;
			while (low<=high) {
    
    
				int middle = low +(high-low)/2;
				if (numbers[middle]==target-numbers[i]) {
    
    
					 return new int[]{
    
    i + 1, middle + 1};
				}else if (numbers[middle]>target-numbers[i]) {
    
    
					high=middle-1;
				}else {
    
    
					low=middle+1;
				}
			}
		}
    	return new int[0];
    }
}

复杂度分析

img


344. 反转字符串——简单

题目描述

img

题解

方法一:倒叙输出

class Solution {
    
    
    public void reverseString(char[] s) {
    
    
        StringBuffer sb = new StringBuffer();
    	for (int i = s.length-1; i >=0; i--) {
    
    
			 sb.append(s[i]);
		}
    	for(int i=0;i<sb.length();i++) {
    
    
    		s[i] = sb.charAt(i);
    	}
    }
}

复杂度分析

img

方法二:reserve()反转

class Solution {
    
    
    public void reverseString(char[] s) {
    
    
    	StringBuffer sb = new StringBuffer();
    	for(int i=0;i<s.length;i++) {
    
    
    		sb.append(s[i]);
    	}
    	sb=sb.reverse();
    	
    	for(int i=0;i<sb.length();i++) {
    
    
    		s[i] = sb.charAt(i);
    	}
    }
}

复杂度分析

img

方法三:双指针

class Solution {
    
    
    public void reverseString(char[] s) {
    
    
    	int p1 = 0;
    	int p2 = s.length-1;
    	char a;
    	while (p1<p2) {
    
    
    		a = s[p1];
    		s[p1++] = s[p2];
    		s[p2--] = a;
		}
    }
}

复杂度分析

img

img


557. 反转字符串中的单词 III——简单

题目描述

img

题解

方法一:字符串分割反转

class Solution {
    
    
    public String reverseWords(String s) {
    
    
    	StringBuffer sb = new StringBuffer();
    	String a[] = s.split(" ");
    	
    	for (int i = 0; i < a.length; i++) {
    
    
			StringBuffer sb2 = new StringBuffer(a[i]);
			sb2 = sb2.reverse();
			if (i!=a.length-1) {
    
    
				sb.append(sb2+" ");
			}else {
    
    
				sb.append(sb2);
			}
    	}
    	s = sb.toString();
    	return s;
    }	
}

复杂度分析

img


876. 链表的中间结点——简单

题目描述

img

题解

思路:

方法一:快慢指针法

快指针q每次走2步,慢指针p每次走1步,当q走到末尾时p正好走到中间。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    
    public ListNode middleNode(ListNode head) {
    
    
    	ListNode p1 = head;
    	ListNode p2 = head;
    	while (p2!=null&&p2.next!=null) {
    
    
			p1 = p1.next;
			p2 = p2.next.next;
		}
    	return p1;
    }
}

复杂度分析

img

img

方法二:List数组

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    
    public ListNode middleNode(ListNode head) {
    
    
    	List<ListNode> list = new ArrayList<>();
    	while (head!=null) {
    
    
    		list.add(head);
    		head = head.next;
		}
    	int middle = list.size();
		middle = middle/2;
    	return list.get(middle);
    }
}

img


19. 删除链表的倒数第 N 个结点——中等

题目描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

img

img

示例 2:

img

示例 3:

img

img

题解

方法一:双指针

img

img

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    
    public ListNode removeNthFromEnd(ListNode head, int n) {
    
    
    	ListNode p1 = head;
    	ListNode p2 = head;
    	if (head==null||head.next==null) {
    
    
			return null;
		}
        // 先让快指针走n步
    	for(int i=0;i<n;i++) {
    
    
			p1 = p1.next;
    	}
        // 如果快指针走到了最后说明删除的是第一个节点,就返回head.next就好
    	if(p1 == null) {
    
    
    		return head.next;
    	}
    	while (p1.next!=null) {
    
    
			p1 = p1.next;
			p2 = p2.next;
		}
    	p2.next = p2.next.next;
    	return head;
    	
    }
}

复杂度分析

img

img


猜你喜欢

转载自blog.csdn.net/qq_45696377/article/details/122645036