LeetCode做题总结:数组

本来是想直接复习数据结构的,但学姐建议我最好的复习方式是做题。对学姐的建议我是服气的,她的确很擅长学习。我现在刚刚开始在LeetCode上做题,实在不好意思用“刷”这个词,我做题是真的慢,实不相瞒,算法一直是我的软肋。好多时候自己根本找不到好的思路,所以在这里把我的思考过程,还有从别人那里借鉴到的好的思路都整理出来,日积月累总会有帮助。

刚接触LeetCode,我选择的语言是java,看题目时没有给main方法,我以为是要自己写的,写了半天,感觉不对劲:为什么题目没有给输入终止条件?然后还傻乎乎的跑到别人博客下面去留言。后来百度了一下才知道LeetCode上面等于说是提供了main函数的,只要把方法体里的内容补全,人家自己就会测试了,真是尴尬啊。啰啰嗦嗦的开了个篇,下面进入正题了。

 一.旋转数组

 

给定一个数组,将数组中的元素向右移动 个位置,其中 是非负数。

示例 1:

输入: [1,2,3,4,5,6,7]k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入: [-1,-100,3,99]k = 2
输出: [3,99,-1,-100]
解释: 
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

说明:

  • 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
  • 要求使用空间复杂度为 O(1) 的原地算法。
我的错误分析:
设置一个Arraylist将数组放进去,然后继续将前Length-k个元素添加到这个Arraylist里然后再将排在前边的这些元素去掉,将剩下的再转为数组输出。
然后在本地答案是对的,在LeetCode上,一毛一样的测试用例答案就不对了。呵呵呵大约是人家本身就不想让我用Java里封装好的现成办法偷懒吧,这是我写的:
import java.lang.reflect.Array;
import java.util.*;

class Solution1 {
	public static  void main(String args[]){
		int[] arr={1,2,3,4,5,6,7};
		System.out.println(arr.length);
		int k=3;
     Solution1 solution1=new Solution1();
	solution1.removeDuplicates(arr,k);

	}



	public void removeDuplicates(int[] nums,int k) {
		int q = nums.length;
		List<Integer> list = new ArrayList<>();
		List<Integer> list1 = new ArrayList<>();
		for (int i = 0; i < nums.length; i++) {
			list.add(nums[i]);
			list1.add(nums[i]);
		}

		for (int a = 0; a <= q - k - 1; a++) {
			list.add(list.get(a));
		}
		//System.out.println(list);
		for (int m = 0; m < q - k; m++) {
			list.remove(0);
		}
		System.out.println(list);

	}
}
然后本地结果也是对的:
7
[5, 6, 7, 1, 2, 3, 4]

Process finished with exit code 0

重点来看下正确的分析思路:

以及具体的代码实现:

class Solution {
    public void rotate(int[] nums, int k) {
       int n=nums.length;
        if(k>n){
			k=k%n;
		}
		int[] nums2=new int[n-k];
		int[] nums3=new int[k];
		System.arraycopy(nums,0,nums2,0,n-k);
		//System.out.println(Arrays.toString(nums2));
		System.arraycopy(nums,n-k,nums3,0,k);
		//System.out.println(Arrays.toString(nums3));
		nums2=reverse(nums2);
		nums3=reverse(nums3);
		int i=0;
		for(int j=k-1;j>=0;j--){
			nums[i]=nums3[j];
			i++;
		}
		for(int j=n-k-1;j>=0;j--){
			nums[i]=nums2[j];
			i++;
		}
		System.out.println(Arrays.toString(nums));
    }
    private int[] reverse(int[] arr) {
        for(int i=0;i<arr.length/2;i++){
        	int temp=arr[i];
        	arr[i]=arr[arr.length-i-1];
        	arr[arr.length-i-1]=temp;
		}
		return arr;
	}
}

二.加一

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。

示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
这个题需要注意的点就是进位的问题。如果数组中原来存的是【9,9,9】。那么末位加一后的数组应该是【1,0,0,0】,而不是【9,9,10】。

这个题我解的不怎么样,这篇博客里的解答还不错给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组。(数组加1)

三.存在重复

给定一个整数数组,判断是否存在重复元素。

如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

示例 1:

输入: [1,2,3,1]
输出: true

示例 2:

输入: [1,2,3,4]
输出: false

示例 3:

输入: [1,1,1,3,3,4,3,2,4,2]
输出: true

这道题我利用了Set中不能有重复元素,把数组放到Set里面,然后看Set和数组的大小是否相等。过的还是挺轻松的。

import java.util.HashSet;
import java.util.Set;

public class Solution3 {
	public boolean containsDuplicate(int[] nums) {
		Set<Integer> set=new HashSet<>();
		for(int a:nums){
			set.add(a);
		}
		if(set.size()==nums.length)
    return false;
		return true;
	}
	public static void main(String args[]){
		int[] arr={1,2,3,1};
		Solution3 solution3=new Solution3();
		solution3.containsDuplicate(arr);
		System.out.println(solution3.containsDuplicate(arr));
	}
}

四.移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

说明:

  1. 必须在原数组上操作,不能拷贝额外的数组。
  2. 尽量减少操作次数。

 

这是我一开始做的:
class Solution {
    public void moveZeroes(int[] nums) {
        for(int i=0;i<nums.length;i++){
       	if(nums[i]==0){
       		//找到了0,要把后面所有元素都前移
			for(int j=i+1;j<nums.length;j++){
				nums[j-1]=nums[j];
			}
			nums[nums.length-1]=0;
		}
	   }
		System.out.println(Arrays.toString(nums));
    }
}

循环整个数组,在找到0元素之后,把它后面的元素都往前移动。但在有两个零连在一起的时候,无法得出正确结果。真是让人困扰啊~

正确解法

统计0出现的个数num,每当遇到不为0的元素,就将它与前第num个元素交换,并且将这个元素所处的位置赋值为0.

class Solution {
    public void moveZeroes(int[] nums) {
        int zero=0;
        for(int i=0;i<nums.length;i++){
       	if(nums[i]==0)
       		zero++;
//这里设置的条件是排除只有一个数组元素并且其不为0的情况
		else if(zero!=0) {
            nums[i-zero]=nums[i];
            nums[i]=0;
        }	
		 }
		System.out.println(Arrays.toString(nums));
    }
}

 五.从排序数组中删除重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2], 

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums.length == 0) return 0;
        int i = 0;
        for(int j = 1; j < nums.length; j++) {
            if(nums[j] != nums[i]) { // 有序数组的判重,只要看元素和前一个元素是否重复
                i++;
                nums[i] = nums[j];
            }
        }
        return i+1;

		
    }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值