【DAY 22——数组专题】
第五题:数组中出现次数超过一半的数字
分析:遇到相同的数则+1,遇到不同的数则-1.
class Solution {
public int majorityElement(int[] nums) {
int len = nums.length;
int count = 0;
int major = nums[0];
int total = 0;
for(int i = 0;i < len;i++){
if(count == 0){
major = nums[i];
}
if(nums[i] == major){
count++;
}
else{
count--;
}
}
if(count > 0){
for(int j = 0;j < len;j++){
if(major == nums[j]){
total++;
}
}
if(total > len/2){
return major;
}
else{
return 0;
}
}
return 0;
}
}
第六题:调整数组顺序,使奇数位于偶数前面
分析:设置两个哨兵i,j。
I从头开始,假设所指的数为奇数,则往前,为偶数则不动;
j从最后开始,假设所指的数为偶数,则往前,为奇数,则不动;
当两个指针都不动的时候(i指向偶数,j指向奇数),交换位置,直到i>j
//执行用时:2 ms, 在所有 Java 提交中击败了99.72% 的用户
//内存消耗:46 MB, 在所有 Java 提交中击败了99.53% 的用户
class Solution {
public int[] exchange(int[] nums) {
int i = 0,j = nums.length-1;
int temp;
while(i < j){
if((nums[i] % 2 == 0)&&(nums[j] % 2 != 0)){
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++;
j--;
}
if(nums[i] % 2 != 0){
i++;
}
if(nums[j] % 2 == 0 ){
j--;
}
}
return nums;
}
}
第七题:旋转数组的最小数字
分析:这样的话,旋转数组最大值的后面一位就是最小值?
错,因为可能存在多个最大值,要找到最后一个
(但是不知道为什么,他给出的测试用例直接就是一个递增序列)
以最小值的点为分界,与最后一个数组元素比较,比他小的肯定排在最小值的右边,同理,比他大的排在最小值的左边,而且,最小值的左右边都是一个递增数列。
因此,利用这个特性,假如当前的这个数组元素比最后一个数大,则只需要查找该数的右半部分,否则,只需要查找该数的左半部分。这样的话,搜查的范围不断缩小一半,最终找到最小值所在的位置。
【DAY 23——数组专题】
第八题:连续子数组的最大和*(动态规划)*
分析:从这一题开始学习动态规划!首先看到题目第一反应是滑动窗口,但是想来就很复杂,因为这个子数组并没有限制长度。假如,以nums[i]为子数组的结束值,假如前边的数为正,则可加上,为负,则不加。
动态规划思想的精髓就是:1.要让第(n)步达到最值,那么第(n-1)步也要达到最值;2.且第(n)步受第(n-1)步影响;3.大问题都是由若干相同解法的子问题组成,只要满足这个条件的题,就可以用动态规划。
下一步就是构建模型:
1.状态,即子问题;
dp[i]代表以元素num[i]结尾的连续子数组最大和;
2.转移策略,自带剪枝;
假如dp[n-1] <= 0,则若加上,带来的只是负影响,因此还不如只要nums[i]
3.状态转移方程,根据前两步抽象而来;
假如dp[n-1] <= 0:执行dp[i] = nums[i];
否则,执行dp[i] = dp[i-1] + nums[i];
4.设计dp数组,保存子问题的解,避免重复计算。(像这一题就是将子数组解的值对应到dp数组相应的下标上,比较整个数组元素的值即可)
5.代码实现
//执行用时:1 ms, 在所有 Java 提交中击败了99.37% 的用户
//内存消耗:44.5 MB, 在所有 Java 提交中击败了99.72% 的用户
class Solution {
public int maxSubArray(int[] nums) {
int len = nums.length;
int[] dp = new int[len];
dp[0] = nums[0];
for(int i = 1;i < len;i++){
if(dp[i-1] > 0){
dp[i] = dp[i-1] + nums[i];
}
else{
dp[i] = nums[i];
}
}
int max = dp[0];
for(int j = 0;j < len;j++){
if(dp[j] > max){
max = dp[j];
}
}
return max;
}
}
//这个是上边的内存优化版本,将上边的数组用两个变量former和cur来表示
//这里的cur有两个作用,一是指向当前的nums[i],二是保存当前子问题的值(和max比较,假如比max大,则更新max)
//执行用时:1 ms, 在所有 Java 提交中击败了99.37% 的用户
//内存消耗:44.6 MB, 在所有 Java 提交中击败了99.44% 的用户
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0];
int former = 0;//用于记录dp[i-1]的值,对于dp[0]而言,其前面的dp[-1]=0
int cur = nums[0];//用于记录dp[i]的值
for(int num:nums){
cur = num;
if(former>0) cur +=former;
if(cur>max) max = cur;
former=cur;//更新former
}
return max;
}
}
第九题:早餐组合
分析:第一反应肯定是直接两层for…,或者一层for另一个数组遍历。
更优的解法是,将两个数组从小到大排序,设定两个哨兵,每个数组各一个,哨兵A从staple的头部出发,哨兵B从drinks的尾部出发,一大一小这样容易凑到(从中间开始凑用二分法也可),并且省时(因为凑到了x元,那么比尾部的大数小的数都满足条件,就不必遍历)。
//执行用时:86 ms, 在所有 Java 提交中击败了54.91% 的用户
//内存消耗:57.8 MB, 在所有 Java 提交中击败了86.82% 的用户
class Solution {
public int breakfastNumber(int[] staple, int[] drinks, int x) {
Arrays.sort(staple);
Arrays.sort(drinks);
int i = 0;
int j = drinks.length-1;
int ans = 0;
while(i <= staple.length-1 && j >= 0){
if(staple[i] + drinks[j] > x){
j--;
}
else{
ans += j+1;
ans %= 1000000007;//
i++;
}
}
return ans;
}
}
第十题:0~n-1中缺失的数字
分析:
第一种思路:还是之前那个以空间换时间的方法;
第二种思路:第一个nums[i]不等于i的数就是缺失的数(假如说所有数都在和他下标相同的位置,那么缺少的就是最后那个数,也就是nums.lenth+1);思路二的实现有两种方法:二分查找、双指针
第三种思路:直接顺序遍历,碰到第一个nums[i]!=i的输出,然后再加上两个情况,1.所有数都错位(缺了0);2.所有数都顺位(缺了最后一个数)。
技巧总结:看到有序数组——>二分/双指针——>既是查找问题,某种情况下也能作为判断某个数是否存在的问题
//第一种思路的实现:
//执行用时:1 ms, 在所有 Java 提交中击败了7.11% 的用户
//内存消耗:38.8 MB, 在所有 Java 提交中击败了98.45% 的用户
class Solution {
public int missingNumber(int[] nums) {
int n = nums.length+1;
int[] A = new int[n];
// int temp;
Arrays.fill(A,-1);
for(int i = 0;i < n-1;i++){
// temp = nums[i];
// A[temp] = nums[i];
A[nums[i]] = nums[i];
}
for(int j = 0;j < n;j++){
if(A[j]==-1){
return j;
}
}
return 0;
}
}
//执行用时:0 ms, 在所有 Java 提交中击败了100.00% 的用户
//内存消耗:38.8 MB, 在所有 Java 提交中击败了98.56% 的用户
class Solution {
public int missingNumber(int[] nums) {
int i = 0, j = nums.length - 1;
while(i <= j) {
int m = (i + j) / 2;
if(nums[m] == m) i = m + 1;
else j = m - 1;
}
return i;
}
}
作者:jyd
链接:https://leetcode-cn.com/problems/que-shi-de-shu-zi-lcof/solution/mian-shi-ti-53-ii-0n-1zhong-que-shi-de-shu-zi-er-f/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【DAY24——数组专题】
第十一题:最小的K个数(Top-k)
分析:这种求top-k的,一半可以用快排、堆、冒泡这种不用排完序就知道最值的排序来解决。
//第一种方法:大根堆/小根堆(java默认大根堆,python默认小根堆),假如说新来的节点比堆的根节点还大,那么就不入堆,否则入堆然后重新排树,最后留下的就是最小的个数。
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
int[] vec = new int[k];
if (k == 0) { // 排除 0 的情况
return vec;
}
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer num1, Integer num2) {
return num2 - num1;
}
});
for (int i = 0; i < k; ++i) {
queue.offer(arr[i]);
}
for (int i = k; i < arr.length; ++i) {
if (queue.peek() > arr[i]) {
queue.poll();
queue.offer(arr[i]);
}
}
for (int i = 0; i < k; ++i) {
vec[i] = queue.poll();
}
return vec;
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/zui-xiao-de-kge-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
//第二种思路:快排的优化。
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
randomizedSelected(arr, 0, arr.length - 1, k);
int[] vec = new int[k];
for (int i = 0; i < k; ++i) {
vec[i] = arr[i];
}
return vec;
}
public void randomizedSelected(int[] arr, int l, int r, int k) {
if (l >= r) {
return;
}
int pos = randomizedPartition(arr, l, r);
int num = pos - l + 1;
if (k == num) {
return;
} else if (k < num) {
randomizedSelected(arr, l, pos - 1, k);
} else {
randomizedSelected(arr, pos + 1, r, k - num);
}
}
// 基于随机的划分
public int randomizedPartition(int[] nums, int l, int r) {
int i = new Random().nextInt(r - l + 1) + l;
swap(nums, r, i);
return partition(nums, l, r);
}
public int partition(int[] nums, int l, int r) {
int pivot = nums[r];
int i = l - 1;
for (int j = l; j <= r - 1; ++j) {
if (nums[j] <= pivot) {
i = i + 1;
swap(nums, i, j);
}
}
swap(nums, i + 1, r);
return i + 1;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/zui-xiao-de-kge-shu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。