LeeCode——Array

Easy

Move Zeros

在这里插入图片描述
代码:

public class Solution {
	 public static void moveZeroes(int[] nums) {
		    if (nums == null || nums.length == 0) {
		        return;
		    }
		    
		    int cur = 0;//该指针等到0出现的那一刻,就会一直指向0,因此需要将他所指向的元素给temp.回头给 nums[i]
//		    共有cur和i两个指针,如果一开始元素不为0,那么i指向谁,cur也指向谁,
//		    但后续cur++后cur会比i大1,比如i=0时,执行循环完后,cur=1  i=1时,执行完循环后cur=2;
//		    但如果遇到元素为0了,i指针会继续往下走,但cur指针会停留在最后++后的地方。如i=2时,元素为0,那么循环就执行结束
//		    且cur没有++,还是2。接着i=3时,执行循环,temp用来装cur所在位置的元素,即为0,再把i现在所在位置的元素移到cur位置
//		    ,然后cur++.最后把temp(0)移到i所在的位置。执行完毕后,cur又指向了0元素,如果下一个元素是0,i就继续往下走,直到碰到
//		    非0元素,再与cur位置的元素(0)交换。
		    for (int i = 0; i < nums.length; ++i) { // 没碰到0元素之前,都是元素自己给自己赋值,然后交换自己。
		        if (nums[i] != 0) {
		            int temp = nums[cur];
		            nums[cur++] = nums[i];//将nums[i]的非0元素给0元素所在位置nums[cur++]
		            nums[i] = temp;
		        }
		    }
		}
	 public static void main(String[] args) {
		 int[] arr=new int[] {1,3,0,1,1,0,0,0,2};
		 moveZeroes(arr);
		 for(int i:arr) {
			System.out.print(i+" ");
		 }
	}

}

交换位置那边换成如下更好理解一些:

	for(int i = 0; i < nums.length; i++) {
        if(nums[i] != 0) {
            int temp = nums[j];
            nums[j] = nums[i];
            nums[i] = temp;
            j++;
        }
    }

Jewels and Stones

在这里插入图片描述
Note:

  • S and J will consist of letters and have length at most 50.
  • The characters in J are distinct.

解答:
1.使用正则表达式:

class Solution {
    public int numJewelsInStones(String J, String S) {
        return S.replaceAll("[^"+J+"]","").length();
//        return S.replaceAll("[^J]","").length();这样写会将J当作一个普通的数字,而非字符串
//            [abc] : 表示可能是a,可能是b,也可能是c
//        	  [^abc] : 表示不是a,b,c中的任意一个
    }
}

2.使用集合

class Solution {
    public static int numJewelsInStones(String J, String S) {
       int cnt=0;
       Set set=new HashSet();
       for(char s:J.toCharArray()) {//将J中的字母都扔到集合中
    	   set.add(s);
       }
       for(char s:S.toCharArray()) {
    	   if(set.contains(s)) {//挨个看看S中的字符set集合中是否拥有
    		   cnt++;
    	   }
       }
       return cnt;
    }
    public static void main(String[] args) {
    	int cnt=numJewelsInStones("abc","213sd2ac");
    	System.out.println(cnt);//2
	}
}

344. Reverse String

在这里插入图片描述
解答:
1.两个指针一前一后扫描交换

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

169.Majority Element

在这里插入图片描述
代码:

public class Solution {
    public int majorityElement(int[] num) {
    	/*
    	 * 设置一个指针用来计数,指向第一个元素,此时指针值为1,然后以此往后
    	 * 碰到相同元素,指针值+1,否则-1,如果指针值为0,说明此时并没有一个值more than
    	 * n/2。但也存在一个问题,如果数组里没有元素>n/2,那会出问题,如,1,2,3,4,5
    	 * 最终count=1,return的element是5,但显然5不符合要求。因此假设数组中
    	 * 总是存在the majority element十分重要。
    	 */
        int major=num[0], count = 1;
        for(int i=1; i<num.length;i++){
            if(count==0){
                count++;
                major=num[i];
            }else if(major==num[i]){
                count++;
            }else count--;
            
        }
        return major;
    }
}

代码图解:
在这里插入图片描述

242. Valid Anagram

在这里插入图片描述
代码:

public class Solution {
    public boolean isAnagram(String s, String t) {
        int[] alphabet = new int[26];
        for (int i = 0; i < s.length(); i++) //跟计数/桶排序一样,往桶(0-26范围)里面存值
        	alphabet[s.charAt(i) - 'a']++;  //注意一下,arr['b'-'a']等价于arr[1]。即arr['b'-'a']==arr[1]
        for (int i = 0; i < t.length(); i++) //在对应的桶里面取值
        	alphabet[t.charAt(i) - 'a']--;
        for (int i : alphabet) //如果两个数组的元素都是一样的话,那此时桶对应的值应该都为0。
        	if (i != 0) return false;
        return true;
    }
}

注意:
数组的长度表示可以用arr.length,而字符串的长度表示要用s.length()
s.charAt(i) - 'a’这样能够保证这差值是大于等于0,小于等于25的——‘a’=97,‘z’=122,122-97=25。长度是122-97+1=26。所以alphabet数组长度为26.

217. Contains Duplicate

在这里插入图片描述
代码:
我自己做的:一个简单的计数排序搞定

class Solution {
    public boolean containsDuplicate(int[] nums) {
        int max=nums[0];
        for(int i:nums){
            if(i>max) max=i;
        }
        int[] bask=new int[max+1];
        for(int i:nums){
            bask[i]++;
        }
        boolean flag=false;
        for(int i:bask)
            if(i>1)
                flag= true;
        return flag;
    }
}

第二种方法:使用HashTable

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> distinct=new HashSet<Integer>();
        for(int i:nums){
            if(distinct.contains(i))//若集合中存在,那么代表是重复的。
                return true;
            else  
                distinct.add(i);//不重复就将该元素添加进集合中。
        }
        return false;
    }
}

第三种方法,先排序,再比较也是一种不错的思路

	public boolean containsDuplicate(int[] nums) {
        Arrays.sort(nums);//先排序
        for(int ind = 1; ind < nums.length; ind++{
            if(nums[ind] == nums[ind - 1]) {
                return true;
            }
        }
        return false;
    }

最大子列和问题

122. Best Time to Buy and Sell Stock II

在这里插入图片描述
在这里插入图片描述
该题可以分段求和,并非求最大子列和问题,因此会简单许多。
代码:

public class Solution {
	public int maxProfit(int[] prices) {
		//price={7,1,5,4,6,3}
		int total = 0;
		for (int i = 0; i < prices.length - 1; i++) {
			if (prices[i + 1] > prices[i])
				total += prices[i + 1] - prices[i];
		}

		return total;
	}
}

这边给出了7,1,5,4,6,3。
显然,5-1以及6-4这两段之和为最大值。
第二种写法:

class Solution {
    public int maxProfit(int[] prices) {
        int maxCur=0;
        for(int i=1;i<prices.length;i++){
            maxCur=maxCur+(prices[i]-prices[i-1]>0 ? prices[i]-prices[i-1]:0);
        }
        return maxCur;
    }
}

121. Best Time to Buy and Sell Stock

在这里插入图片描述
这是一道最大子列和问题:
代码:

public class Solution {
	public int maxProfit(int[] prices) {
		int maxCur = 0, maxSoFar = 0;
		for (int i = 1; i < prices.length; i++) {
			maxCur = Math.max(maxCur += prices[i] - prices[i - 1], 0);
			//maxCur=maxCur+Math.max(0,prices[i]-prices[i-1]);适用于可以分段求和的情况,而非这边的连需求和情况。
			maxSoFar = Math.max(maxCur, maxSoFar);
		}
		return maxSoFar;
	}
}

注:这边的maxCur = Math.max(0, maxCur += prices[i] - prices[i - 1]);
等同于maxCur = Math.max(0, maxCur + prices[i] - prices[i - 1]);
maxCur用来存储当前的子列和情况,只要不小于0,就会一直累加。
maxSoFar用来存储目前位置的最大子列和。

原理图:
在这里插入图片描述

53. Maximum Subarray

最大子列和问题
下面这种方法具有很大普遍性,针对全是复数的数组也适用。
代码:

public class Solution {
	public static int maxSubArray(int[] A) {
		int n=A.length;
		int maxCur=A[0];
		int maxAll = A[0];
		for (int i = 1; i < n; i++) {
			maxCur = (maxCur > 0 ? maxCur : 0) + A[i];
			//(maxCur > 0 ? maxCur : 0)等价于Math.max(maxCur,0)
			//好好体会上面这行代码,意味深长,如果有正有负的数组第一个元素是负数,
			//那么判断下来maxCur>0不成立,置为0,maxCur=A[1];
			maxAll = Math.max(maxCur, maxAll);
		}
		return maxAll;
	}
}

注:
上边代码中maxCur与maxAll不能取为0,因为碰到元素都为负数的情况,会出错。因为元素都是负数,maxAll就会一直取0,但0并非给定数组中的元素。

总结:连续求最大和问题必须要用两个指针(maxCur和maxAll),分段求和问题只需要使用一个指针(最简单的情况)。

202. Happy Number

在这里插入图片描述
这是一道Floyd判圈算法(Floyd Cycle Detection Algorithm)
该算法的原理:龟兔绕着圆环赛跑
在这里插入图片描述
在这里插入图片描述
代码:

public class Solution {
	public static boolean isHappy(int n) {
		int slow = n;
		int fast = n;
		do {
			slow = digitSquareSum(slow);
			fast = digitSquareSum(fast);
			fast = digitSquareSum(fast); //为什么fast有两个,目的就是为了让快的指针追上慢的指针
		} while (slow != fast); //直到slow=fast,该do-while循环才结束
		if (slow == 1)
			return true;
		else
			return false;
	}

//  用来求一个数每个数字的平方和
	public static int digitSquareSum(int n) {
		int sum = 0, tmp = 0;
		while (n != 0) {
			tmp = n % 10;
			sum += tmp * tmp;
			n /= 10;
		}
		return sum;
	}

	public static void main(String[] args) {
		boolean num = isHappy(19);
		System.out.println(num);
	}
}

至于为什么fast与slow相等就停呢?因为继续往下走,永远都是一样的结果了。可以动手再试试。
在这里插入图片描述
代码2:使用Set集合

public class Solution {
	public static boolean isHappy(int n) {
		Set<Integer> set = new HashSet<Integer>();
		int squareSum=0, remain=0;
		while (set.add(n)==true) { //直到出现与集合中有重复的数字才停止
//			如果出现重复数字,也就意味着下面的这段循环操作等都是重复的
			squareSum = 0;
			while (n > 0) {	//求各项数字之和
				remain = n % 10;
				squareSum += remain * remain;
				n /= 10;
			}
			if (squareSum == 1)
				return true;
			else
				n = squareSum;//如果和不等于1就赋给n,继续计算,直到和为1或者集合中已经有这个值位置

		}
		return false;

	}

	public static void main(String[] args) {
		boolean num = isHappy(20);
		System.out.println(num);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值