陣列基礎
文件講解︰程式碼隨想錄(programmercarl.com)
1.連續空間、相同型別元素
2.元素只能覆蓋
3.二維陣列的地址連續嗎(C++連續,Java不連續)
704. 二分查詢
題目連結:704. 二分查詢
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰二分查詢
日期:2024-08-29
思路:第一反應是想到二分查詢的前提:陣列升序,無重複元素;第二點是,確定區間是左閉右開還是左閉右閉,這樣才能確定是左右大小比較是<、還是<=。
Java程式碼如下:
//左閉右閉
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){
int mid = left + (right - left)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] < target){
left = mid + 1;
}else{
right = mid - 1;
}
}
return -1;
}
}
//左閉右開
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length;
while(left < right){
int mid = left + (right - left)/2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] < target){
left = mid + 1;
}else{
right = mid;
}
}
return -1;
}
}
程式碼隨想錄給出一個最佳化的版本:
class Solution {
public int search(int[] nums, int target) {
// 避免當 target 小於nums[0] nums[nums.length - 1]時多次迴圈運算
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
return mid;
}
else if (nums[mid] < target) {
left = mid + 1;
}
else { // nums[mid] > target
right = mid - 1;
}
}
// 未找到目標值
return -1;
}
}
總結:還要再熟悉下更新mid,尋找區間是左閉右開區間,right更新為mid而不是mid - 1,即:下一個查詢區間不會去比較nums[middle]。
27. 移除元素
題目連結:27. 移除元素
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰移除元素
日期:2024-08-29
思路:1.暴力解法,兩層for,一層遍歷陣列找要移除的目標值,另一層是找到移除的值後,將其後面的值移前一位;2.快慢指標:快指標快在它會先走,遍歷整個陣列,慢指標:如果快指標遇到目標值了,它就不動了,否則將快指標的值給它,這樣的好處就是,兩個指標都從開頭起步,能很方便的找到目標值並用後面的值覆蓋。
Java程式碼如下:
//暴力
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length;
for(int i = 0; i < size; i++){
if(nums[i] == val){
for(int j = i + 1; j < size; j++){
nums[j - 1] = nums[j];
}
i--;
size--;
}
}
return size;
}
}
//快慢指標
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
for(int fast = 0; fast < nums.length; fast++){
if(nums[fast] != val){
nums[slow++] = nums[fast];
}
}
return slow;
}
}
程式碼隨想錄還提供了用相向雙指標的演算法,我用的是同向的:
//相向雙指標法
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length - 1;
while(right >= 0 && nums[right] == val) right--; //將right移到從右數第一個值不為val的位置
while(left <= right) {
if(nums[left] == val) { //left位置的元素需要移除
//將right位置的元素移到left(覆蓋),right位置移除
nums[left] = nums[right];
right--;
}
left++;
while(right >= 0 && nums[right] == val) right--;
}
return left;
}
}
總結:第一次用雙指標的地方,之前面試有被問過什麼時候用雙指標的地方,後面遇到多了再總結。總的來說就是一邊迴圈裡幹兩遍迴圈的事。
977.有序陣列的平方
題目連結:977.有序陣列的平方
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰有序陣列的平方
日期:2024-08-29
思路:1.暴力思路,平方後再快排; 2.注意到陣列是有序的,那麼對於平方後的最大數只會在頭或者尾產生,所有兩個指標一個在頭一個在尾平方比大小,把較大的值放到一個新陣列的末尾就行了。
Java程式碼如下:
class Solution {
public int[] sortedSquares(int[] nums) {
int[] result = new int[nums.length];
int left = 0;
int right = nums.length - 1;
int i = nums.length - 1;
while(left <= right){
if(nums[left] * nums[left] <= nums[right] * nums[right]){
result[i--] = nums[right] * nums[right];
right--;
}else{
result[i--] = nums[left] * nums[left];
left++;
}
}
return result;
}
}
總結:注意一定要是有序的陣列才能這麼操作,面試被坑過(
209.長度最小的子陣列
題目連結:209.長度最小的子陣列
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰長度最小的子陣列
日期:2024-08-29
思路:看題第一眼就是滑動視窗(總算記住了),陣列跟著前指標的移動逐加,直到和大於等於目標,記錄此時子陣列長度,此時移動一位後指標,前指標再接著走,接著加,再出現大於等於目標時比較之前的長度和這一次的,取最小值,最後返回時還要判斷到底存不存在這個子陣列
Java程式碼如下:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
int i = 0, sum = 0;
for(int j = 0; j < nums.length; j++){
sum += nums[j];
while(sum >= target){
result = Math.min((j - i + 1), result);
sum -= nums[i++];
}
}
return result == Integer.MAX_VALUE? 0: result;
}
}
總結:不熟悉Java語法,Integer.MAX_VALUE,Math.min,滑動視窗這名字還是很形象的,主要用在早最小區間。
59.螺旋矩陣II
題目連結:59.螺旋矩陣II
文件講解︰程式碼隨想錄(programmercarl.com)
影片講解︰螺旋矩陣II
日期:2024-08-29
思路:首先是找不變數,在本題中就是區間的劃分,上下左右都得是同樣的區間(左閉右開)才能清楚明白的寫下去,還有就是完成這套題需要一些什麼值要搞清楚,迴圈起始位置(怎麼調整它:需要一個調整值),迴圈次數,填的數(從1開始),最後就是這個二維矩陣的中心有沒有,確定了這些思路就清楚了
Java程式碼如下:
class Solution {
public int[][] generateMatrix(int n) {
int result[][] = new int[n][n];
int startx = 0, starty = 0;
int loop = n / 2;
int mid = n / 2;
int offset = 1;
int count = 1;
while(loop-- > 0){
int i = startx;
int j = starty;
for(; j < n - offset; j++){
result[i][j] = count++;
}
for(; i < n - offset; i++){
result[i][j] = count++;
}
for(; j > 0; j--){
result[i][j] = count++;
}
for(; i > 0; i--){
result[i][j] = count++;
}
startx++;
starty++;
offset++;
}
if(n % 2 != 0) result[mid][mid] = n * n;
return result;
}
}
總結:錯在了對二維陣列兩個角標的理解上,還有這裡每個值的意義要搞明白。