1. 程式人生 > >LeetCode刷題記錄(一)

LeetCode刷題記錄(一)

LeetCode刷題記錄(一)

最近開始在LeetCode上面做題,想想應該做一個記錄,以便以後看到類似的問題及時查閱,同時也能夠將做題時的思路記錄下來,將這些思路整理歸納,形成一套我自己的解題思路。當然,演算法題只做一次是不夠的,需要多次的練習,可能每次的想法都不太一樣,在這裡我只將當時做題的想法記錄下來,不一定是這道題目的最優解,以後發現更好的解法的時候我也會及時更新。因為是剛開始做題,所以除了題目特殊要求之外,我暫時還未完全考慮優化演算法的時間和空間複雜度,後續再做的時候就需要考慮這方面的問題了。

我沒有按照題目的順序往下面做,而是先挑選卡片進行專項練習的,最近我做的是陣列和字串卡片下面的題目,也是相對較為簡單的內容。

1、尋找陣列的中心索引

題目:

這裡寫圖片描述

我的思路:

  1. 首先需要計算陣列所有元素的和sum;
  2. 然後遍歷陣列每個元素,計算剔除當前元素後陣列所有元素的和tmp;
  3. 計算當前元素左側所有元素的和;
  4. 如果左側元素的和*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、至少是其他數字兩倍的最大數

題目:

這裡寫圖片描述

我的思路:

  1. 首先需要獲取到這個陣列的最大元素;
  2. 然後遍歷陣列中除了最大元素的所有元素,如果某個元素*2>最大元素的話,說明不符合題目要求,可以直接結束;
  3. 如果陣列中除了最大元素之外所有元素都滿足*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. 遍歷這個陣列,計算這個陣列代表的整數;
  2. 將這個整數+1,得到新的整數;
  3. 將新的整數拆解成陣列,得到最後的結果。

這種實現方式表面上看實現了題目中要求的功能,但是實際上是沒有考慮資料型別最大值的情況,以int型別為例,我們都知道在Java中int型別是32位的,最大值是2,147,483,647,也就是說如果遍歷陣列得到的整數大於這個最大值,那麼+1得到的結果也就毫無意義了。那如果我們將計算結果定義為long型,也是不能解決問題的,因為long型也有最大值的問題。那浮點型呢?也是不行的,而且浮點型還會有精度的問題,所以說這個思路是錯誤的。

後來我又想到了一個新的思路,既然這個陣列每一位都代表了一個整數的每一位,那麼我們能不能就直接按照加法的規則去計算結果呢?什麼是加法的規則?最簡單的就是如果這個數最後一位+1≥10,那麼最後一位置0,它需要向前進位,讓前面的數也+1,以此類推。如果計算到第一位仍然需要進位,那麼就在數字最前面補1,這樣一來解題的思路就很清晰了。

改進後的思路:

  1. 判斷陣列最後一位+1是否<10,如果是,則只需要將最後一位+1即可;
  2. 如果陣列最後一位+1≥10,那麼就將最後一位置為0並向前進位,判斷前一位+1是否≥10,如果是,仍然置0並向前進為,以此類推;
  3. 如果得到的陣列第一位是0,說明需要新建一個數組,陣列長度為原陣列長度+1,並且這個陣列的第一位為1,其餘位均為0;
  4. 如果得到的陣列第一位不為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;
    }
}