Leetcode训练算法入门——双指针全刷
Posted 胡毛毛_三月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode训练算法入门——双指针全刷相关的知识,希望对你有一定的参考价值。
目录
- [977. 有序数组的平方](https://leetcode-cn.com/problems/squares-of-a-sorted-array/)——简单
- [189. 轮转数组](https://leetcode-cn.com/problems/rotate-array/)——中等
- [283. 移动零](https://leetcode-cn.com/problems/move-zeroes/)——简单
- [167. 两数之和 II - 输入有序数组](https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/)——简单
- [344. 反转字符串](https://leetcode-cn.com/problems/reverse-string/)——简单
- [557. 反转字符串中的单词 III](https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/)——简单
- [876. 链表的中间结点](https://leetcode-cn.com/problems/middle-of-the-linked-list/)——简单
- [19. 删除链表的倒数第 N 个结点](https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/)——中等
977. 有序数组的平方——简单
题目描述
题解
方法一:直接排序
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) 的栈空间进行排序。
方法二:双指针
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. 轮转数组——中等
题目描述
题解
方法一:使用额外的数组
我们可以使用额外的数组来将每个元素放至正确的位置。用 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. 移动零——简单
题目描述
题解
方法一:
//思路:设置一个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++;
方法二:双指针
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;
复杂度分析
167. 两数之和 II - 输入有序数组——简单
题目描述
题解
方法一:双指针
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];
复杂度分析
方法二:二分查找
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];
复杂度分析
344. 反转字符串——简单
题目描述
题解
方法一:倒叙输出
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);
复杂度分析
方法二: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);
复杂度分析
方法三:双指针
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;
复杂度分析
557. 反转字符串中的单词 III——简单
题目描述
题解
方法一:字符串分割反转
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;
复杂度分析
876. 链表的中间结点——简单
题目描述
题解
思路:
方法一:快慢指针法
快指针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;
复杂度分析
方法二: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);
19. 删除链表的倒数第 N 个结点——中等
题目描述
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
示例 2:
示例 3:
题解
方法一:双指针
/**
* 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;
复杂度分析
以上是关于Leetcode训练算法入门——双指针全刷的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode训练剑指 Offer(专项突击)——双指针全刷