Array结构 数组为什么从0开始.
1 2 3 int foo[5 ] = {1 ,2 ,3 ,4 ,5 };foo[0 ] *(foo + 0 )
1 2 a[3][4] a[0][0], a[0][1] , a[0][2] , a[0][3]
https://developer.51cto.com/article/649423.html
LEETCODE 26 https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
解法: 双指针
首先注意数组是有序的,那么重复的元素一定会相邻。
要求删除重复元素,实际上就是将不重复的元素移到数组的左侧。
考虑用 2 个指针,一个在前记作 p,一个在后记作 q,算法流程如下:
比较 p 和 q 位置的元素是否相等。
如果相等,q 后移 1 位 如果不相等,将 q 位置的元素复制到 p+1 位置上,p 后移一位,q 后移 1 位 重复上述过程,直到 q 等于数组长度。
返回 p + 1,即为新数组长度。
Nums[p] == nums[q] q 后移1位
Nums[p] != nums[q]. Nums[p+1] = nums[q]. p 后移1位, q后移1位
Nums[p] != nums[q] 。。。。
上图向下的箭头,只代表步骤,不代表指针位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 fun removeDuplicates1 (nums: IntArray ) : Int { if (nums.isEmpty()){ return 0 } var slowIndex = 0 for (fastIndex in 1 until nums.size) { if (nums[fastIndex] != nums[slowIndex]) { nums[slowIndex + 1 ] = nums[fastIndex] slowIndex++ } } return slowIndex+1 } fun removeDuplicates (nums: IntArray ) : Int { if (nums.isEmpty()){ return 0 } var slowIndex = 1 for (fastIndex in 1 until nums.size) { if (nums[fastIndex] != nums[slowIndex - 1 ]) { nums[slowIndex] = nums[fastIndex] slowIndex++; } } return slowIndex }
1 2 3 4 5 6 7 8 9 10 11 12 fun moveZeroes (nums: IntArray ) : Unit { var slowIndex = 0 for (fastIndex in 1 until nums.size) { if (nums[fastIndex] != 0 && nums[slowIndex] == 0 ) { nums[slowIndex] = nums[fastIndex] nums[fastIndex] = 0 } if (nums[slowIndex] != 0 ) { slowIndex++ } } }
栈 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 fun backspaceCompare1 (s: String , t: String ) : Boolean { val sStack = Stack<Char >() for (i in s.indices) { if (s[i] == '#' ) { if (sStack.isNotEmpty()) { sStack.pop() } } else { sStack.push(s[i]) } } val tStack = Stack<Char >() for (j in t.indices) { if (t[j] == '#' ) { if (tStack.isNotEmpty()) { tStack.pop() } } else { tStack.push(t[j]) } } return sStack == tStack }
双指针1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 fun backspaceCompare (s: String , t: String ) : Boolean { var i = s.length - 1 var j = t.length - 1 var skipS = 0 var skipT = 0 while (i >= 0 && j >= 0 ) { while (i >= 0 ) { if (s[i] == '#' ) { skipS++ i-- } else if (skipS > 0 ) { skipS-- i-- } else { break } } while (j >= 0 ) { if (t[j] == '#' ) { skipT++ j-- } else if (skipT > 0 ) { skipT-- j-- } else { break } } if (i >= 0 && j >= 0 ) { if (s[i] != t[j]) { return false } } else if (i >= 0 || j >= 0 ) { return false } i-- j-- } return true }
https://leetcode-cn.com/problems/backspace-string-compare/solution/shuang-zhi-zhen-bi-jiao-han-tui-ge-de-zi-8fn8/
双指针2 这种双指针写法也不错,只是最后的String.valueOf不同语言有出入,和这个题目意思有点对不上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public boolean backspaceCompare(String s, String t) { // equals()判断返回的两个字符串是否相等 return changeString(s).equals(changeString(t)); } public static String changeString (String str) { // 先将字符串转为数组,方便使用双指针法 char[] x = str.toCharArray(); int slow = 0; for (int fast = 0; fast < x.length; fast++) { // 当x[fast] != '#'时,x[fast]覆盖x[slow],然后slow++ if (x[fast] != '#') x[slow++] = x[fast]; // 当x[fast] = '#'且slow!=0时,slow-- else if(x[fast] == '#' && slow != 0) slow--; } // 返回字符串 return String.valueOf(x, 0, slow); } } https://leetcode-cn.com/problems/backspace-string-compare/solution/shuang-zhi-zhen-fa-si-lu-jian-dan-rong-y-bmn6/
有序数组的平方 left ,right 左右两端比较大小,大的放新数组的最右端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fun sortedSquares (nums: IntArray ) : IntArray { var left = 0 var right = nums.size - 1 var index = nums.size - 1 val arrayNew = IntArray(nums.size) while (left <= right) { val leftSquare = nums[left] * nums[left] val rightSquare = nums[right] * nums[right] if (leftSquare <= rightSquare) { arrayNew[index--] = rightSquare right-- } else { arrayNew[index--] = leftSquare left++ } } return arrayNew }
https://leetcode-cn.com/problems/squares-of-a-sorted-array/solution/c-dong-hua-yan-shi-977-you-xu-shu-zu-de-gxlvm/
双指针(滑动窗口) 滑动窗口主要找到移动左指针的条件
其实就是精简出暴力解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 fun minSubArrayLen(target: Int, nums: IntArray): Int { var sum = 0 var leftP = 0; var result = Int.MAX_VALUE for (rightP in nums.indices) { sum += nums[rightP] while (sum >= target) { val subLength = rightP - leftP + 1 if (subLength < result) result = subLength sum -= nums[leftP++] } } if (result == Int.MAX_VALUE) result = 0 return result }
**一些录友会疑惑为什么时间复杂度是O(n)**。
不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被被操作两次,所以时间复杂度是 2 × n 也就是O(n)。
对于这个解释 o(n)其实我还是有一些不理解.
https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/209-chang-du-zui-xiao-de-zi-shu-zu-hua-dong-chua-7/
暴力解法 先移动前面的,再移动后面的遍历找出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : int minSubArrayLen (int s, vector<int >& nums) { int result = INT32_MAX; int sum = 0 ; int subLength = 0 ; for (int i = 0 ; i < nums.size (); i++) { sum = 0 ; for (int j = i; j < nums.size (); j++) { sum += nums[j]; if (sum >= s) { subLength = j - i + 1 ; result = result < subLength ? result : subLength; break ; } } } return result == INT32_MAX ? 0 : result; } }; 时间复杂度:O (n^2 ) 空间复杂度:O (1 ) 作者:carlsun-2 链接:https: 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处.
双指针(滑动窗口)
题目不好懂 [1,2,3,2,2]. , 1 ,2,3,数字大小分别表示水果树类别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 fun totalFruit (fruits: IntArray ) : Int { var leftP = 0 var basketList = mutableMapOf<Int , Int >() var result = 0 var subLength: Int for (rightP in fruits.indices) { val element = fruits[rightP] if (basketList.containsKey(element)) { basketList[element] = basketList[element]!!.plus(1 ) } else { basketList[element] = 1 } while (true ) { if (basketList.size > 2 ) { basketList[fruits[leftP]] = basketList[fruits[leftP]]!!.minus(1 ) if (basketList[fruits[leftP]] == 0 ) { basketList.remove(fruits[leftP]) } leftP++ } else { subLength = rightP - leftP + 1 if (subLength > result) { result = subLength } break } } } return result }
1 2 3 4 5 6 7 8 9 上面解法 if (basketList.containsKey(element)) { basketList[element] = basketList[element]!!.plus(1 ) } else { basketList[element] = 1 } 可以用这一句替换 basketList[element] = basketList.getOrDefault(element, 0 ).plus(1 )
滑动窗口 (sliding window)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 ** * 核心思想: s的 left right,已经覆盖了t字串,那么就移动left,看看是否还在范围内 * 通过判断T中A B C都 >0 没被抵消, <0 说明 s有多余这个字符个数 */ class LC76 { fun minWindow (s: String , t: String ) : String { val map = mutableMapOf<Char , Int >() for (element in t) { map[element] = map.getOrDefault(element, 0 ).plus(1 ) } var leftP = 0 var rightLast = 0 var resultLength = Int .MAX_VALUE var resultStr = "" for (rightP in s.indices) { if (map.containsKey(s[rightP])) { map[s[rightP]] = map.getOrDefault(s[rightP], 0 ).minus(1 ) } while (isMatch(map, t)) { val subLength = rightP - leftP + 1 if (subLength < resultLength) { rightLast = rightP resultLength = subLength resultStr = s.substring( leftP, rightLast + 1 ) } if (map.containsKey(s[leftP])) { map[s[leftP]] = map.getOrDefault(s[leftP], 0 ).plus(1 ) } leftP++ } } return resultStr } private fun isMatch (map: Map <Char , Int >, t: String ) : Boolean { for (element in t) { if (map[element]!! > 0 ) { return false } } return true } }
视频讲解很清晰
https://leetcode-cn.com/problems/minimum-window-substring/solution/zui-xiao-fu-gai-zi-chuan-by-leetcode-solution/
这道题参考去看看 labuladong解法,我没找到,后面再看看,
螺旋矩阵 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 fun generateMatrix (n: Int ) : Array<IntArray> { var left = 0 var top = 0 var right = n - 1 var bottom = n - 1 var num = 1 val target = n * n var arr = Array(n) { IntArray(n) } while (num <= target) { for (i in left..right) arr[top][i] = num++ top++ for (i in top..bottom) arr[i][right] = num++ right-- for (i in right downTo left) arr[bottom][i] = num++ bottom-- for (i in bottom downTo top){ arr[i][left] = num++ } left++ } return arr }
题解根据下面这个解法,简单巧妙
https://leetcode-cn.com/problems/spiral-matrix-ii/solution/spiral-matrix-ii-mo-ni-fa-she-ding-bian-jie-qing-x/