3.16–3.22刷题总结
- LeetCode篇
- 两数之和
据说是leetcode入门必刷题,小菜鸡在遇到这种题第一反应:暴力!!! 嗯 ,那肯定是不行的,所以,在众多资料中,成功使用HashMap完成了这个题呢。
暴力法得时间复杂度为O(n2),在要求降低时间复杂度的情况下,则必须用空间来换。
HashMap:
建立数字与其坐标位置之间的映射,遍历一个数,另一个预先存储。
思路:
target - 遍历到的数字 = 另一个需要的数字(直接查找是否存在该数)
步骤:
1) 建立对象,新建数组用来存放索引;
2) 遍历数组,建立HashMap映射;
3)二次查找并记录索引。
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> m = new HashMap<Integer,Integer>();
int[] res =new int[2];
for(int i=0 ; i < nums.length ; ++i){
m.put(nums[i],i);
}
for(int i=0 ; i < nums.length ; ++i){
int t = target -nums[i];
if(m.containsKey(t) && m.get(t) != i){//m.containsKey(k) 判断是否包含指定的键值
res[0]=i;
res[1]=m.get(t);
break;
}
}
return res;
}
}
要求:
不使用额外的数组空间,必须在原地修改输入数组并使用O(1)额外空间的条件下完成。
思路:
因为数组是有序的,所以只需要用后面的元素覆盖前面重复的数即可。使用快慢指针来记录遍历的坐标。
1)开始时两个指针都指向第一个数;
2)若两个数相同,则快指针向前一步;
3)若两个数不同,则快慢指针都向前一步。
则当快指针走完整个数组后,慢指针当前坐标+1既是数组中不同数字的个数。
class Solution {
public int removeDuplicates(int[] nums) {
int j = 0;//慢指针
int i = 1 ;//快指针
for(; i < nums.length ; i++){
if(nums[i] != nums[j]){
j++;
nums[j]=nums[i];
}
}
return j+1 ;
}
}
要求:
使用空间复杂度为O(1)的原地算法解决问题。
思路:
这个旋转数组的解法有很多中,自己做不出来的情况参考了一下大佬的思路
个人比较喜欢类似字符翻转的方式,嘻嘻嘻嘻嘻哈哈哈哈哈哈 (k->翻转次数)
1) 先把前 n-k 个数字翻转一下;
2)再把后 k 个数字翻转 ;
3)再把整个数组翻转。
在Java中可以使用ArrayList数组,调用Collections.reverse方法实现翻转(小声哔哔 使用Collections.reverse的前提是 数组是ArrayList类型滴)。
(以下,是提交代码)
class Solution {
public void rotate(int[] nums, int k) {
int n=nums.length;
if(nums.length==0 || (k=k%nums.length)==0) return;
reverse(nums,0,n-k-1);
reverse(nums,n-k,nums.length-1);
reverse(nums,0,nums.length-1);
}
public void reverse(int[] nums, int start,int end){ //翻转函数
while(start<end){
int t=nums[start];
nums[start++] = nums[end] ;
nums[end--] = t ;
}
}
}
- 只出现一次的数字
这是一道很神奇的题! 用异或运算符简单解决问题!
异或运算符:
其是一种基于二进制的位运算,运算符两侧数的每个二进制位同值取0,异值取1.
还可解决的问题:
1)一个数组存放若干整数,一个数出现奇数此,其余数均出现偶数次,找出这个穿线奇数次的数。
2)1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次,每个数组元素只能访问一次,不用辅助存储空间,找出该值。
class Solution {
public int singleNumber(int[] nums) {
int res=0;
for(int i=0;i<nums.length;i++){
res^=nums[i];
}
return res;
}
}
- 66-加一
本题较为简单,但存在一个特殊情况,若数组为 [9] ,则返回 [1,0] 。 这种情况要单独写。
class Solution {
public int[] plusOne(int[] digits) {
int a = digits.length ;
for(int i=a-1;i>=0;i--){
if(digits[i]==9){//末尾数为9 向前进一
digits[i]= 0;
}else{
digits[i]++;//非9 情况
return digits ;
}
}
digits =new int[a+1]; //特殊情况
digits[0] =1;
return digits;
}
}
- 移动零
思路:
双指针解决问题。一个不停的后移,寻找非0位,当找到后与前面的指针交换位置即可。
class Solution {
public void moveZeroes(int[] nums) {
for (int i = 0, j = 0 ; i <nums.length ; i++) {
if(nums[i]!=0){//j每当有一个非0值前移,j++
int t=nums[j];
nums[j++]=nums[i];
nums[i]=t;
}
}
}
}
- 两个数组的交集☆
思路:
1)定义一个HashSet型数组set用来存放nums1的数据,因为HashSet的特性,nums1中重复的元素已被过滤。
2)定义一个ArrayList型数组arr用来存放最后输出的数据。
3)数组set可通过循环键入nums1的数据,在键入arr时循环nums2数组,此时可使用x.contains()方法来判断nums2数组中的元素在set中是否存在,如果存在,arr增加且set删除该数据(因为要求输出的每个元素是唯一的,如果不从set中删除,nums2中与nums1相同的元素会多次输出)。
4)将ArrayList型数组转化为int型数组输出。
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> set = new HashSet<>();
ArrayList<Integer> arr = new ArrayList<>();
for(int num : nums1) set.add(num);
for(int num : nums2){
if(set.contains(num)) {
arr.add(num);
set.remove(num);
}
}
int[] res = new int[arr.size()];
for(int i = 0; i < arr.size(); i++)
res[i] = arr.get(i);
return res;
}
}
- 字符串中的第一个唯一字符
思路:
1)假定该字符串中只包含小写字母,建立一个int型数组存放26个字母出现的次数;
2) 使用循环记录每个字母出现的次数;
3) 再次循环,将字符串中的字母与记录数组中的数据对比,输出第一个唯一字符
其中:
x.toCharArray() 方法是将字符串转换为字符数组,输出结果是字符数组。
class Solution {
public int firstUniqChar(String s) {
int[] len=new int[26];//存储各字符出现次数
for (char c:s.toCharArray())//第一次遍历
len[c-'a']++;
for (int i = 0; i <s.length() ; i++) {//第二次遍历
if(len[s.charAt(i)-'a']==1)
return i;
}
return -1;//无解
}
}
- 使数组唯一的最小增量
题目含义:
将数组中存在的数都使其唯一,若存在重复的数,加上最小增量使其成为唯一。
思路:
1)数组排序
2)若A[i-1]==A[i],则A[i]++;
3)若A[i-1] > A[i] , A[i] = A[i-1] + 1 。
class Solution {
public int minIncrementForUnique(int[] A) {
Arrays.sort(A); //对数组排序
int res = 0 ;
for(int i=1 ; i<A.length ; i++ ){
if( A[i-1]==A[i] ){ //当排序后 如果相连的两个数值相等 则后者则增 (不需要管后者大于前者的情况)
A[i]++;
res++;
}
if( A[i-1] > A[i] ){ //当增加操作使得 相邻元素前者大于后者 则res在两数之差上增加1,小元素在大元素的基础上+1
res = res + A[i-1] - A[i] + 1 ;
A[i] = A[i-1] + 1 ;
}
}
return res ;
}
}
在摸索中前进,希望自己不会后悔!
奥利给!