双指针 EASY 21.11.13
26.删除有序数组中的重复项
我的解法
class Solution {
public int removeDuplicates(int[] nums) {
int len = nums.length, n = 0;
if (len == 0 || len == 1){
return len;
}
//创建一个新数组记录不重复的数字
int[] sorted = new int[len];
//遍历原数组,如果不相同就记录进新数组,相同就记录数组的长度减一
//n是新数组的指针,当有非重复数字记录进新数组时,n++
sorted[0] = nums[0];
for (int i = 1; i < nums.length; i++){
if (sorted[n] != nums[i]){
sorted[n + 1] = nums[i];
n++;
}else {
len--;
}
}
//len是记录没有重复数字的数组长度,将新数组赋值给nums的前len位
for (int j = 0; j < len; j++){
nums[j] = sorted[j];
}
return len;
}
}
执行用时:1 ms, 在所有 Java 提交中击败了96.24%的用户
内存消耗:39.7 MB, 在所有 Java 提交中击败了75.83%的用户
官方解法
不借助新的数组媒介,因为直接覆盖的要么是原元素,要么是重复的元素。
class Solution {
public int removeDuplicates(int[] nums) {
int n = nums.length;
if (n == 0){
return 0;
}
int flat = 1, slow = 1;
while (flat < n){
if (nums[flat] != nums[slow - 1]){
nums[slow] = nums[flat];
slow++;
}
flat++;
}
return slow;
}
}
执行用时:1 ms, 在所有 Java 提交中击败了96.24%的用户
内存消耗:39.4 MB, 在所有 Java 提交中击败了95.73%的用户
88.合并两个有序数组
我的解法
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int index = 0;
for (int i = 0; i < n; i++){
while (index < m + i){
if (nums2[i] <= nums1[index]){
insert(nums1, i, index, m);
nums1[index] = nums2[i];
break;
}
index++;
}
nums1[index] = nums2[i];
}
}
public void insert(int[] nums1, int i, int index, int m){
for (int j = m + i; j > index; j--)
nums1[j] = nums1[j - 1];
}
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.1 MB, 在所有 Java 提交中击败了96.39%的用户
官方解法
2.1 合并后排序
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
for (int i = m; i < m + n; i++){
nums1[i] = nums2[i - m];
}
Arrays.sort(nums1);
}
}
执行用时:1 ms, 在所有 Java 提交中击败了17.63%的用户
内存消耗:38.4 MB, 在所有 Java 提交中击败了75.55%的用户
2.2 双指针
该方法借助了新的数组
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int[] sorted = new int[m + n];
int p1 = 0, p2 = 0;
while (p1 < m || p2 < n){
if (p1 == m){
sorted[p1 + p2] = nums2[p2];
p2++;
}else if (p2 == n){
sorted[p1 + p2] = nums1[p1];
p1++;
}else if (nums1[p1] > nums2[p2]){
sorted[p1 + p2] = nums2[p2];
p2++;
}else {
sorted[p1 + p2] = nums1[p1];
p1++;
}
}
for (int i = 0; i < m + n; i++){
nums1[i] = sorted[i];
}
}
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.3 MB, 在所有 Java 提交中击败了88.29%的用户
2.3 逆向双指针
该方向可以避免覆盖。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = m - 1, p2 = n - 1;
while (p1 > -1 || p2 > -1){
if (p1 == -1){
nums1[p1 + p2 + 1] = nums2[p2];
p2--;
}else if (p2 == -1){
nums1[p1 + p2 + 1] = nums1[p1];
p1--;
}else if (nums1[p1] > nums2[p2]){
nums1[p1 + p2 + 1] = nums1[p1];
p1--;
}else {
nums1[p1 + p2 + 1] = nums2[p2];
p2--;
}
}
}
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.2 MB, 在所有 Java 提交中击败了92.05%的用户
27.移除元素
我的解法
借助了新数组媒介
class Solution {
public int removeElement(int[] nums, int val) {
int index = 0, n = nums.length;
if (n == 0){
return 0;
}
int[] sorted = new int[n];
for (int i = 0; i < n; i++){
if (nums[i] != val){
sorted[index] = nums[i];
index++;
}
}
for (int j = 0; j < index; j++){
nums[j] = sorted[j];
}
return index;
}
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:37 MB, 在所有 Java 提交中击败了50.39%的用户
官方解法
1、双指针
直接在原数组上改动
class Solution {
public int removeElement(int[] nums, int val) {
int index = 0, n = nums.length;
if (n == 0){
return 0;
}
for (int i = 0; i < n; i++){
if (nums[i] != val){
nums[index] = nums[i];
index++;
}
}
return index;
}
}
2、双指针优化
用左右双指针,避免重复赋值操作
0 | 1 | 2 | 2 | 3 | 0 | 4 | 2 | val=2 |
---|---|---|---|---|---|---|---|---|
0 | 1 | 4 | 0 | 3 |
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0, right = nums.length;
while (left < right){
if (nums[left] == val){
nums[left] = nums[right - 1];
right = right - 1;
}else {
left++;
}
}
return left;
}
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.6 MB, 在所有 Java 提交中击败了97.94%的用户