# Go Leetcode: Two Pointer ###### tags: `leetcode` `go` ## Container With Most Water ### #1 ```go= func maxArea(height []int) int { i, j := 0, len(height) - 1 max := 0 for i < j { // main logic cur_prod := min(height[i], height[j]) * (j-i) if max < cur_prod { max = cur_prod } if height[i] < height[j] { // left move for i < j { i++ if height[i] > height[i-1] { break } } } else { // right move for i < j { j-- if height[j] > height[j+1] { break } } } } return max } func min(i, j int) int { if i < j { return i } else { return j } } ``` ### #2 refactor ```go= func maxArea(height []int) int { i, j := 0, len(height) - 1 max := 0 for i < j { // main logic if height[i] < height[j] { max = maxx(max, height[i] * (j-i)) // left move for i < j { i++ if height[i] > height[i-1] { break } } } else { max = maxx(max, height[j] * (j-i)) // right move for i < j { j-- if height[j] > height[j+1] { break } } } } return max } func maxx(i, j int) int { if i < j { return j } else { return i } } ``` ### #3 extremely fast ```go= func init() { in := bufio.NewScanner(os.Stdin) in.Buffer(nil, math.MaxInt32) _out, _ := os.Create("user.out") // create file. must be "user.out" for leetcode out := bufio.NewWriter(_out) for in.Scan() { s := in.Bytes() n := bytes.Count(s, []byte{','}) + 1 // count amount of "," ans, l, r, i, j, readL, readR := 0, 0, n-1, 0, len(s)-1, true, true var x, y int for l < r { if readL { readL = false i++ x = int(s[i] & 15) i++ for s[i]&15 < 10 { x = x*10 + int(s[i]&15) i++ } } if readR { readR = false for j -= 2; s[j]&15 < 10; j-- { } k := j + 1 // j is indes of "," y = int(s[k] & 15) k++ for s[k]&15 < 10 { y = y*10 + int(s[k]&15) k++ } } ans = max(ans, min(x, y)*(r-l)) if x < y { l++ readL = true } else { r-- readR = true } } fmt.Fprintln(out, ans) } out.Flush() os.Exit(0) } func maxArea([]int) (_ int) { return } func max(a, b int) int { if b > a { return b } return a } func min(a, b int) int { if a > b { return b } return a } ``` ## Two Sum II - Input Array Is Sorted ### #1 hash map ```go= func twoSum(numbers []int, target int) []int { m := make(map[int]int) // number: index for i, n := range numbers { pair := target - n if m[pair] > 0 { return []int{m[pair], i+1} } m[n] = i+1 } return []int{} } ``` ### #2 two pointers ```go= func twoSum(numbers []int, target int) []int { l, r := 0, len(numbers)-1 for { sum := numbers[l] + numbers[r] if sum > target { r-- } else if sum < target { l++ } else { return []int{l+1, r+1} // sum = target } // should not happen if l >= r { return []int{} } } } ``` ## Three Sum ### #1 fail ```go= func threeSum(nums []int) [][]int { // time: O(n) m := make(map[int][]int) for i, n := range nums { m[n] = append(m[n], i) } fmt.Println(m) // time: <= O(n2) res := [][]int{} for l := 0; l < len(nums); l++ { first := nums[l] for r := l+1; r < len(nums); r++ { second := num[r] third := 0-first-second } } return res } func sliceEqual(a, b []int) bool { if len(a) != len(b) { return false } sort.Ints(a) sort.Ints(b) for i:= 0; i<len(a); i++ { if a[i] != b[i] { return false } } return true } ``` ### #2 close but fail ```go= func threeSum(nums []int) [][]int { sort.Ints(nums) res := [][]int{} for i, a := range nums { l, r := i+1, len(nums)-1 for l< r { b, c := nums[l], nums[r] sum := a + b + c if sum > 0 { r-- } else if sum < 0 { l++ } else { res = append(res, []int{a, b, c}) l++ } } } return res } ``` ``` input: [-1,0,1,2,-1,-4] output: [[-1,-1,2],[-1,0,1],[-1,0,1]] expected: [[-1,-1,2],[-1,0,1]] ``` ### #3 success ```go func threeSum(nums []int) [][]int { sort.Ints(nums) res := [][]int{} for i, a := range nums { // ignore same value if i > 0 && a == nums[i-1] { continue } l, r := i+1, len(nums)-1 for l< r { b, c := nums[l], nums[r] sum := a + b + c if sum > 0 { r-- } else if sum < 0 { l++ } else { res = append(res, []int{a, b, c}) l++ // if next num equals to prev for nums[l] == nums[l-1] && l < r { l++ } } } } return res } ``` ### Note - need to ignore duplicated numbers - is an extension of [Two Sum II](/#) - Time: - sorting: O(nlogn) - finding: O(n2) ## Valid Palindrome ### #3 best ```go= func isPalindrome(s string) bool { l, r := 0, len(s)-1 res := true for l<r { for !check(s[l]) { l++ if l >= r { break } } for !check(s[r]) { r-- if l >= r { break } } if l >= r { break } if !equals(s[l], s[r]) { return false } l++ r-- } return res } func check(char byte) bool { if 'a' <= char && char <= 'z' { return true } else if '0' <= char && char <= '9' { return true } else if 'A' <= char && char <= 'Z' { return true } return false } func equals(a, b byte) bool { if a == b { return true } if 'A' <= a && a <= 'Z' { return a+32 == b // 'a' - 'A' = 32 } else if 'A' <= b && b <= 'Z' { return a == b+32 } return false } ``` ### Resources [用Go刷LeetCode和OJ](https://zhangjk98.xyz/go-oj/)