今天早起了,是宝贵的周六,随着工作量增大,属于自己的时间越来越少,一天之内被紧急的事情打断了三,四次,要开始做好实在不行脱产准备面试的预期了,现在的积蓄可以坚持一年待业,但是心态肯定很难保持,所以不到万不得已还是不希望失去经济来源,只能咬牙再坚持一段时间了,至少要先把简历准备好。
今日进度:
- 网课开始进入难度稍高一点的数组题目,第一次真正使用快速排序的思路解决问题,实现的时候卡住了,参考了一下发现该使用while的地方,使用了if,才发现其实基础的while循环都没有完全理解,while的条件只要为真,就会一直循环下去,在实现快排的时候是非常有用的。
- 坚持锻炼,出去走了一大圈,算是不间断的刷题和上班之间的调节
- 坚持录声音,有时间可以多录一些小王子
- 刷题真的很枯燥,解不出来和修bug的时候也是真的很难受,现在的课程也是刷题为主的,听课和看文档的时间变得非常珍惜了
学习笔记:
- leetcode75
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
示例 1: 输入:nums = [2,0,2,1,1,0] 输出:[0,0,1,1,2,2]
示例 2: 输入:nums = [2,0,1] 输出:[0,1,2]
示例 3: 输入:nums = [0] 输出:[0]
示例 4: 输入:nums = [1] 输出:[1] 提示:
n == nums.length 1 <= n <= 300 nums[i] 为 0、1 或 2
解题思路有两种:
1.计数排序:分别统计0,1,2的元素个数,再在数组中直接赋值
2.三路快速排序:遍历数组,设置三个指针,zero, i, two,元素值等于1的不变,小于1和大于1的分别放在zero的后一个和two的前一个,时间复杂度为O(N),空间复杂度为O(1)
这里的代码是使用第二种方法实现的
class Solution {
public void sortColors(int[] nums) {
int zero = -1;//表示0的结束位置
int two = nums.length;//表示2的开始位置
for (int i=0; i<two;){
if(nums[i] == 1){
i++;
}
else if(nums[i] == 2){
two--;
swap(nums, i, two);
}
else{
assert(nums[i] == 0);
zero++;
swap(nums, i, zero);
i++;
}
}
}
public void swap(int[] n, int a, int b){
int tmp;
tmp = n[a];
n[a] = n[b];
n[b] = tmp;
}
}
- leetcode 88 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2中的元素数目。 请你合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6] 解释:需要合并 [1,2,3] 和 [2,5,6] 。 合并结果是 [1,2,2,3,5,6],其中斜体加粗标注的为 nums1 中的元素。
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1] 解释:需要合并 [1] 和 [] 。 合并结果是 [1] 。
示例 3:
输入:nums1 = [0], m = 0,nums2 = [1], n = 1
输出:[1] 解释:需要合并的数组是 [] 和 [1] 。 合并结果是 [1] 。 注意,因为 m =0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m +n <= 200
-10^9 <= nums1[i], nums2[j] <= 10 ^9
解题思路:使用归并排序的思路,创建一个新的数组,分别遍历两个数组的,将较小的插入新数组,如果一个数组遍历结束,另一个数组还有剩余,将剩余部分直接拷贝到新数组中。将新数组的值拷贝给nums1。时间复杂度为O(M+N),空间复杂度为O(M+N)。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int[] tmp = new int[m+n];
int mi=0;
int ni=0;
for(int i=0; i<m+n; i++){
if(mi > m-1 && ni <= n-1){
for(int j=i; j<m+n; j++){
tmp[j] = nums2[ni];
ni++;
}
break;
}
if(ni > n-1 && mi <= m-1){
for(int j=i; j<m+n; j++){
tmp[j] = nums1[mi];
mi++;
}
break;
}
if(nums1[mi] <= nums2[ni]){
tmp[i] = nums1[mi];
mi++;
}
else{
tmp[i] = nums2[ni];
ni++;
}
}
for(int i=0; i<m+n; i++){
nums1[i] = tmp[i];
}
}
}
- leetcode215 数组中的第K个最大元素
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5
示例 2: 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4
提示: 1 <= k <= nums.length <= 10^4
-10^4 <= nums[i] <= 10 ^4
解题思路:利用快速排序的思路,先找出pivot,第一次排序后,判断K与nums.length-pivot,即pivot是第nums.length-pivot大的元素,如果K小于该值,对pivot右边的数组做递归操作;如果K大于该值,对pivot左边的数组做递归操作,K等于该值,直接返回nums[pivot] 的值。该方法只将数组遍历了一次,时间复杂度为O(N)。
class Solution {
public int findKthLargest(int[] nums, int k) {
int result;
int left = 0;
int right = nums.length-1;
result = qc(nums, left, right, k);
return result;
}
public int qc(int[] n, int l, int r, int k){
int pivot;
pivot = partition(n, l, r);
if((n.length - pivot) == k){
return n[pivot];
}
else if((n.length - pivot) > k){
return qc(n, pivot+1, r, k);
}
else{
return qc(n, l, pivot-1, k);
}
}
public int partition(int[] n, int l , int r){
int pivot = l;
while(l!=r){
while((l<r) && (n[r] > n[pivot])){
r--;
}
while((l<r) && (n[l] <= n[pivot])){
l++;
}
if((l!=r) && (n[r] <= n[pivot] || n[l] > n[pivot])){
int tmp;
tmp = n[r];
n[r] = n[l];
n[l] = tmp;
}
}
int tmp1;
tmp1 = n[pivot];
n[pivot] = n[l];
n[l] = tmp1;
return l;
}
}
现在基本上提示了使用什么算法思路,就可以独立完成刷题了,争取下一步能够不需要提示,自己想出用什么算法思路。刷题很痛苦,但同时也要珍惜这段全力补牢算法基础的时间啊,明天持续更新。