LeetCode刷題記錄(一)
LeetCode刷題記錄(一)
最近開始在LeetCode上面做題,想想應該做一個記錄,以便以後看到類似的問題及時查閱,同時也能夠將做題時的思路記錄下來,將這些思路整理歸納,形成一套我自己的解題思路。當然,演算法題只做一次是不夠的,需要多次的練習,可能每次的想法都不太一樣,在這裡我只將當時做題的想法記錄下來,不一定是這道題目的最優解,以後發現更好的解法的時候我也會及時更新。因為是剛開始做題,所以除了題目特殊要求之外,我暫時還未完全考慮優化演算法的時間和空間複雜度,後續再做的時候就需要考慮這方面的問題了。
我沒有按照題目的順序往下面做,而是先挑選卡片進行專項練習的,最近我做的是陣列和字串卡片下面的題目,也是相對較為簡單的內容。
1、尋找陣列的中心索引
題目:
我的思路:
- 首先需要計算陣列所有元素的和sum;
- 然後遍歷陣列每個元素,計算剔除當前元素後陣列所有元素的和tmp;
- 計算當前元素左側所有元素的和;
- 如果左側元素的和*2等於tmp,說明當前元素左右兩側的和相同,當前元素的索引即是答案
按照這個思路實現的程式碼如下:
class Solution {
public int pivotIndex(int[] nums) {
if(nums.length == 0) {
return -1;
}
//1、計算陣列所有元素的和
int sum = 0;
for(int num : nums) {
sum += num;
}
int index = -1;
//2、遍歷陣列
for(int i = 0; i < nums.length; i++) {
//3、計算剔除當前元素後陣列所有元素的和tmp
int tmp = sum - nums[i];
//4、計算當前元素左側所有元素的和
int tmpSum = 0;
for (int j = 0; j < i; j++) {
tmpSum += nums[j];
}
//5、如果左側元素的和*2=tmp說明當前元素左右兩側元素的和相等,當前元素的索引就是中心索引
if(tmpSum * 2 == tmp) {
index = i;
break;
}
}
return index;
}
}
2、至少是其他數字兩倍的最大數
題目:
我的思路:
- 首先需要獲取到這個陣列的最大元素;
- 然後遍歷陣列中除了最大元素的所有元素,如果某個元素*2>最大元素的話,說明不符合題目要求,可以直接結束;
- 如果陣列中除了最大元素之外所有元素都滿足*2≤最大元素,說明找到了符合條件的元素,該元素的索引就是答案。
按照這個思路實現的程式碼如下:
class Solution {
public int dominantIndex(int[] nums) {
int biggest = 0, bigIndex = -1;
//1、計算陣列中元素的最大值及其索引
for(int i = 0; i < nums.length; i++) {
if(nums[i] > biggest) {
biggest = nums[i];
bigIndex = i;
}
}
int index = -1, count = 0;
//2、遍歷陣列
for(int i = 0; i < nums.length; i++) {
if(i != bigIndex) {
//3、如果存在陣列元素的兩倍比最大值大的情況,說明不符合條件直接跳出迴圈
if(nums[i] * 2 > biggest) {
break;
} else {
count++;
}
}
}
//4、獲取結果
if(count == nums.length - 1) {
index = bigIndex;
}
return index;
}
}
值得注意的是,在這種實現方式裡我定義了一個變數count,這個變數相當於一個計數器,在遍歷陣列的時候,如果陣列元素的值*2≤最大值,那麼count就會遞增,在最後我增加了一個判斷,如果count等於陣列的長度減1說明陣列已經全部遍歷完成(不包括最大的元素),那麼最大元素的索引就是最後的答案。
3、加一
題目:
之前的思路:
- 遍歷這個陣列,計算這個陣列代表的整數;
- 將這個整數+1,得到新的整數;
- 將新的整數拆解成陣列,得到最後的結果。
這種實現方式表面上看實現了題目中要求的功能,但是實際上是沒有考慮資料型別最大值的情況,以int型別為例,我們都知道在Java中int型別是32位的,最大值是2,147,483,647
,也就是說如果遍歷陣列得到的整數大於這個最大值,那麼+1得到的結果也就毫無意義了。那如果我們將計算結果定義為long型,也是不能解決問題的,因為long型也有最大值的問題。那浮點型呢?也是不行的,而且浮點型還會有精度的問題,所以說這個思路是錯誤的。
後來我又想到了一個新的思路,既然這個陣列每一位都代表了一個整數的每一位,那麼我們能不能就直接按照加法的規則去計算結果呢?什麼是加法的規則?最簡單的就是如果這個數最後一位+1≥10,那麼最後一位置0,它需要向前進位,讓前面的數也+1,以此類推。如果計算到第一位仍然需要進位,那麼就在數字最前面補1,這樣一來解題的思路就很清晰了。
改進後的思路:
- 判斷陣列最後一位+1是否<10,如果是,則只需要將最後一位+1即可;
- 如果陣列最後一位+1≥10,那麼就將最後一位置為0並向前進位,判斷前一位+1是否≥10,如果是,仍然置0並向前進為,以此類推;
- 如果得到的陣列第一位是0,說明需要新建一個數組,陣列長度為原陣列長度+1,並且這個陣列的第一位為1,其餘位均為0;
- 如果得到的陣列第一位不為0,只需要將最後需要+1的值+1即可。
按照這個思路實現的程式碼如下:
class Solution {
public int[] plusOne(int[] digits) {
int len = digits.length;
int[] rslt = null;
if(digits[len - 1] + 1 < 10) {
//1、如果陣列最後一個元素(也就是整數最後一位)+1小於10,說明無需進位,直接加1即可
digits[len - 1] = digits[len - 1] + 1;
rslt = digits;
} else {
//2、如果陣列最後一個元素(也就是整數最後一位)+1大於等於10,說明需要進位
//3、因為需要進位,所以從最後一位開始向前遍歷,如果當前位+1大於等於10,則將當前位的值置為0
int i = len - 1;
while(i >= 0 && digits[i] + 1 >= 10) {
digits[i] = 0;
i--;
}
//3、判斷是否所有的位數都置為0,如果是,說明陣列的形式類似於[9,9,9]
//那麼最後的結果應該是一個新的陣列[1,0,0,0],需要新寫一個數組,陣列長度+1,陣列第一位為1,其餘位為0
if(i == -1) {
rslt = new int[digits.length + 1];
rslt[0] = 1;
for(int j = 1; j < rslt.length; j++) {
rslt[j] = 0;
}
} else {
//4、並不是所有位數都為0,所以只需將需要+1的位數+1即可
digits[i] = digits[i] + 1;
rslt = digits;
}
}
return rslt;
}
}