注:點標題能夠查看對應的題目,本文代碼均使用Javascript
編寫。本文代碼不必定是最優解,僅供參考,如仁兄有更好的實現,歡迎交流。javascript
解析:首先要注意關鍵詞,排序數組、原地、不須要考慮數組中超出新長度後面的元素。有這些已知條件,解決起來就簡單不少了。java
思路:git
代碼:es6
/** * @param {number[]} nums * @return {number} */ var removeDuplicates = function(nums) { // 若是數組爲空,直接返回0 if(nums.length === 0){ return 0; } var length = 1; // 不重複值的數量,只要數組不爲空,至少有一個值是不重複的,因此初始值爲1 var temp = nums[0]; // 存儲新的不重複的值 for(var i = 1; i < nums.length; i++){ if(nums[i] !== temp){ temp = nums[i]; // 更新不重複的值 nums[length] = nums[i]; // 更新原數組 length++; // 更新下標 } } return length; // 返回不重複數據數量 };
解析: 這裏使用了貪心算法思想,貪心算法簡單來講就是:局部最優解達成全局最優解。只關心局部最優的解決方法,累加局部最優的的解產生的就是全局最優解。就是把一個複雜的問題拆分紅不少相同的小問題,解決小問題後,大問題也就解決了。使用貪心算法的條件是:局部最優策略能產生全局最優解。有時候局部最優解不一能產生全局最優解,因此在使用以前須要分析。本題獲取最大利潤是全局解,局部最優解是只關心相鄰兩天,只要今天股票比昨天股票價高股就進行交易。算法
思路:數組
代碼:spa
/** * @param {number[]} prices * @return {number} */ var maxProfit = function(prices) { if(!prices || prices.length <= 0){ return; } var maxProfit = 0; // 收益總和 for(var i = 0; i < prices.length - 1; i++){ // 今天股價比昨天股價高,則進行一次買賣操做 if(prices[i] < prices[i + 1]){ maxProfit += prices[i + 1] - prices[i]; // 計算相鄰兩天股票差價的收益 } } return maxProfit; };
解析:這裏k
是非負數,不用考慮向左旋轉的狀況。向右旋轉k
步就是剪切數組末尾的k
項貼到數組頭部。旋轉步數和數組長度同樣時至關於沒有變化。code
代碼:對象
/** * @param {number[]} nums * @param {number} k * @return {void} Do not return anything, modify nums in-place instead. */ var rotate = function(nums, k) { var len = nums.length; k = k % len; // 求餘數,防止k大於數組長度 var temp1 = nums.splice(len - k, k); // 獲取數組末尾的k項 nums.unshift(...temp1); // 拼接到原數組的頭部 };
解析:利用對象記錄當前值是否已存在,對象的屬性名爲當前值。blog
代碼:
/** * @param {number[]} nums * @return {boolean} */ var containsDuplicate = function(nums) { var object = {}; for(var i = 0; i < nums.length; i++){ var cur = nums[i]; // 當前值存在 返回true if(object[cur]){ return true; }else{ // 當前值不存在,記錄一下 object[cur] = true } } return false; // 遍歷完整個數組沒有發現重複的值,則返回false };
解析:使用位運算——異或。異或:相同取0,不一樣取1。
例:3 ^ 4,3的二進制位爲:011,4的二進制爲100,3異或4得出:111,轉回十進制也就是:7。
思路:利用相同的數異或爲0,任何數與0進行異或等於它自己的規則進行查找。這裏實現上使用的是es6
的reduce
方法。
代碼:
/** * @param {number[]} nums * @return {number} */ var singleNumber = function(nums) { return nums.reduce((prev, cur) => (prev ^ cur), 0); // 將0與第一位的數進行異或,得出的結果再與下一位數進行異或 };
解析:求兩個數組的交集,最簡單粗暴的方法就是依次比較兩個數組的值是否相等。這道題看似簡單,實際上網上不少答案都是錯的,他們沒有考慮到比較重複值的狀況。
代碼:
/** * @param {number[]} nums1 * @param {number[]} nums2 * @return {number[]} */ var intersect = function (nums1, nums2) { var result = []; // 交集 var comparedIndex = []; // 記錄比較過的索引值 for (var i = 0; i < nums1.length; i++) { for (var j = 0; j < nums2.length; j++) { // 找出相同的而且還未加入結果的值 if (nums1[i] === nums2[j] && comparedIndex.indexOf(j) === -1) { result.push(nums1[i]); // 加入相同的值 comparedIndex.push(j); // 記錄當前索引值 break; // 找到一個相同的則終止循環體,無需比較後續的值 } } } return result; };
也可使用es6
的filter
方法:過濾出num1
中在num2
中也存在的數據。
代碼:
/** * @param {number[]} nums1 * @param {number[]} nums2 * @return {number[]} */ var intersect = function (nums1, nums2) { const nums2Copy = [...nums2]; // 建一個nums2的備份 return nums1.filter(ele => { const index = nums2Copy.indexOf(ele); // 查看nums2Copy中是否存與當前值相同 if (index !== -1) { // 若是找獲得 nums2Copy.splice(index, 1); // 在nums2Copy中刪除找過的值 return true; // 返回當前值 } }); };
解析:先將數組轉化爲數字,再將數字加一,而後再轉回爲數組。
思路:
注意:字符串過長會致使轉換成數字類型時精度缺失,因此這裏要使用es6
的新數據類型BigInt
代碼:
/** * @param {number[]} digits * @return {number[]} */ var plusOne = function(digits) { var result = digits.join(''); // 數組轉字符串 result = BigInt(result); // 字符串轉BigInt result += BigInt(1); // 加1 result = result.toString().split(''); // 轉換回數組 return result; };
解法二:使用循環,遍歷數組,滿10進1。
代碼:
/** * @param {number[]} digits * @return {number[]} */ var plusOne = function(digits) { const result = [...digits]; // 備份數組 const end = result.length - 1; for(let i = end; i >= 0; i--){ if(result[i] === 9){ // 當前位置的數爲9時 result[i] = 0; // 當前數加一後就變爲0 if(i - 1 >= 0){ // 沒有超過數組長度,直接進行後續循環 continue; }else{ result.unshift(1); // 超過數組元長度,頭部加一位數字1 break; } }else{ result[i] += 1; // 當前位置數字不爲9,直接加1 break; // 不發生進位,跳出循環 } } return result; };
解析:遍歷數組,使用一個遍歷記錄0的數量,當遇到一個0的時候,記錄0的個數,遇到不是0的時候,將當前數的值往前移動與當前0的數量相同距離。並將當前值變爲0。
代碼:
/** * @param {number[]} nums * @return {void} Do not return anything, modify nums in-place instead. */ var moveZeroes = function(nums) { if(nums.length <= 1){ // 數組小於1位,直接返回 return; } var zeroNums = 0; // 當前0的個數 for(var i = 0; i < nums.length; i++){ if(nums[i] === 0){ // 當前值爲0時 zeroNums += 1; // 0的個數加1 }else if(zeroNums > 0){ // 0的數量不爲0時 nums[i - zeroNums] = nums[i]; // 將當前值往前移動zeroNums位 nums[i] = 0; // 將當前值變爲0 } } };
解析:使用雙重循環,每次計算當前索引的值和剩下索引的值的和相加是否爲目標值,是則返回相加的兩個索引值。
代碼:
/** * @param {number[]} nums * @param {number} target * @return {number[]} */ var twoSum = function(nums, target) { var len = nums.length; for(var i = 0; i < len; i++){ for(var j = i + 1; j < len; j++){ if(nums[i] + nums[j] === target){ return [i, j]; } } } };
解析:二維數組,雙重循環是少不了的。校驗的規則很明確有三點,如今有的已知條件是循環是的兩個下標i
和j
,要根據已知條件完成校驗規則的校驗。
思路:
1-9
在每一行只能出現一次。這個其實和以前的數組去重是一個原理,用一個對象記錄一個值是否已經存在,若是存在,第二次在遇到這個值就說明校驗不經過。
1-9
在每一列只能出現一次。列和行的判斷其實同樣,只須要將索引交換便可,例:arr[0][2]
表明第1行的第3個數,那麼arr[2][0]
就表明第1列第三個數。
數字 1-9
在每個以粗實線分隔的 3x3
宮內只能出現一次。
這裏要找規律,宮有9個,行和列表也有9個,若是能找到每一個宮的下標和行列下標(也就是i
和j
)的關係,就能夠循環行的時候對9個宮進行重複數據判斷了。這裏的規律要靠不斷嘗試試出來的,對數字敏感的人想的可能快一下,沒有什麼特定的套路,話很少說,直接上規律:
代碼:
/** * @param {character[][]} board * @return {boolean} */ var isValidSudoku = function (board) { for (var i = 0; i < 9; i++) { var rowShowOnce = {}; // 校驗行是否無重複項 var colShowOnce = {}; // 校驗列是否無重複項 var squareShowOnce = {}; // 校驗宮是否無重複項 for (var j = 0; j < 9; j++) { var row = board[i][j]; // 行的值 var col = board[j][i]; // 列的值 var squareX = 3 * Math.floor(i / 3) + Math.floor(j / 3); // 宮的行座標 var squareY = 3 * (i % 3) + j % 3; // 宮的列座標 var square = board[squareX][squareY]; // 宮的值 // 判斷當前行值在同一行中是否存在 if (row !== '.') { if (rowShowOnce[row]) { return false; // 已存在,行校驗不過,返回false } else { rowShowOnce[row] = true; } } // 判斷當前列值在同一列中是否存在 if (col !== '.') { if (colShowOnce[col]) { return false; // 已存在,列校驗不過,返回false } else { colShowOnce[col] = true; } } // 判斷當前宮值在同一個宮中是否存在 if (square !== '.') { if (squareShowOnce[square]) { return false; // 已存在,宮校驗不過,返回false } else { squareShowOnce[square] = true; } } } } return true; };
解析:這種題通常將變化狀況列舉出來,而後找下標變化規律就好。
第一行:
原下標 | 新下標 | 值 |
---|---|---|
0,0 | 0,2 | 1 |
0,1 | 1,2 | 2 |
0,2 | 2,2 | 3 |
第二行:
原下標 | 新下標 | 值 |
---|---|---|
1,0 | 0,1 | 4 |
1,1 | 1,1 | 5 |
1,2 | 2,1 | 6 |
第三行:
原下標 | 新下標 | 值 |
---|---|---|
2,0 | 0,0 | 7 |
2,1 | 1,0 | 8 |
2,2 | 2,0 | 9 |
不難看出:
可是,這裏題目要求在原地旋轉,當前規律適用於建一個新的矩陣,因此還要想一想其它辦法。
分析:爲達到原地旋轉,每次調整就得一次到位,矩形四條邊,一次調整四個數據的位置。
第一次調整:
步驟 | 原下標 | 新下標 | 值 |
---|---|---|---|
1 | 0,0 | 0,2 | 1 |
2 | 0,2 | 2,2 | 3 |
3 | 2,2 | 2,0 | 9 |
4 | 2,0 | 0,0 | 7 |
第二次調整:
步驟 | 原下標 | 新下標 | 值 |
---|---|---|---|
1 | 0,1 | 1,2 | 4 |
2 | 1,2 | 2,1 | 2 |
3 | 2,1 | 1,0 | 6 |
4 | 1,0 | 0,1 | 8 |
代碼:
/** * @param {number[][]} matrix * @return {void} Do not return anything, modify matrix in-place instead. */ var rotate = function(matrix) { var n = matrix.length; for(var i = 0; i < n / 2; i++){ for(var j = i; j < n - 1 - i; j++){ // 交換兩個值 var temp = matrix[i][j]; matrix[i][j]=matrix[n-1-j][i]; // 步驟4 matrix[n-1-j][i]=matrix[n-1-i][n-1-j]; // 步驟3 matrix[n-1-i][n-1-j]=matrix[j][n-1-i]; // 步驟2 matrix[j][n-1-i]=temp; // 步驟1 } } };