1. 程式人生 > >九章演算法筆記 7.兩根指標 Two Pointers

九章演算法筆記 7.兩根指標 Two Pointers

大綱 cs3k.com

  1. 同向雙指標
  2. 相向雙指標
  3. Two Sum :3.1 大小• = target• <= target • > target     3.2 去重• unique pairs    3.3 離得近• closest to target

    3.4 差

    • difference = target

  4. Partition• Quick Select• 分成兩個部分• 分成三個部分
  5. Sort• 彩虹排序• 烙餅排序• (還有前面學的拓撲排序)• 一些你沒聽過的(但是面試會考的)排序演算法

 

同向雙指標Window Sum 

cs3k.com

Given an array of n integer, and a moving window(size k), move the window at each iteration from the start of the array, find the sum of the element inside the window at each moving.

用prefix sum解,會用extra space

所以就挪一下,加新的,減舊的

同向雙指標Move Zeroes

Given an array nums, write a function to move all 0’s to the end of it while maintaining the relative order of the non-zero elements.

用hash_set, 時間O(n), 快; 但是用extra space

用雙指標, 類似於去重的問題,指標for一下,如果發現不是0,往前填

相向雙指標Rotate String

Given a string and an offset, rotate string by offset. (rotate from left to right).

Given “abcdefg”.

offset=3 => “efgabcd”

做法:

abcd | efg => 兩段分別反序

dcba | gfe => 整體反序

efgabcd

Two Sum

cs3k.com

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are NOT zero-based.

            TIME     SPACE
hash_set    O(n)     O(n)
sort+2p     O(nlogn) O(1)

sort+2pointers方法的指標:

l永遠指向有機會成為二元數組裡面小的那個數

r永遠指向有機會成為二元數組裡面大的那個數

Two Sum – Data structure design 

cs3k.com

Design and implement a TwoSum class. It should support the following operations: add and find.

add – Add the number to an internal data structure.

find – Find if there exists any pair of numbers which sum is equal to the value.

Example

add(1); add(3); add(5);

find(4) // return true

find(7) // return false

雙指標要求是有序序列,因為不斷再加入新的元素, 所以只能用trie樹(平衡二叉樹), 但是trie樹又很慢.

所以就hash_set啦~

Two Sum – Unique pairs 

cs3k.com

Given an array of integers, find how many unique pairs in the array such that their sum is equal to a specific target number. Please return the number of pairs.

比如:

        1 1' 2 45 46 46'   target:92            
        l             r

不能開始去重, 後面去

在第一次做第一個1和最後一個46已經把所有和1和46相關的解找光了, 所以後面就直接跳過

3 Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

            TIME     SPACE
hash_set    O(n^2)     O(n)
sort+2p     O(n^2)     O(1)

先排個序, 固定a, 在a的右面找b+c= -a

Triangle Count 

cs3k.com

Given an array of integers, how many three numbers can be found in the array, so that we can build an triangle whose three edges length is the three numbers that we find?

a…….b…….c…

如果a可以和b c組隊,那麼[a,b)都可以

所以固定b和c挨個挪a

統計所有方案需要O(n^3)

如果只需要方案的個數的話, 差不多O(n^2)

Two Sum – Closest to target

Given an array nums of n integers, find two integers in nums such that the sum is closest to a given number, target.

Return the difference between the sum of the two integers and the target.

記錄一下difference就可以了

3 Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers.

You may assume that each input would have exactly one solution.

for迴圈其中一個, 另外兩個做2 sum closest

Two Sum – Difference equals to target

Given an array of integers, find two numbers that their difference equals to a target value.

where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are NOT zero-based.

同向指標

Partition Array 

cs3k.com

Given an array nums of integers and an int k, partition the array (i.e move the elements in “nums”) such that:

All elements < k are moved to the left All elements >= k are moved to the right

Return the partitioning index, i.e the first index i nums[i] >= k.

有兩種型別:

  1. 分左右

     

  2. 分左中右

左右兩個指標l和r

l的意思: l-1及之前的部分是小於k的

並且從左往右找第一個不應該在左邊的

r的意思: r+1及之後的部分是大於等於k的

從右往左找第一個不應該在右邊的

public class Solution {
    /** *@param nums: The integer array you should partition *@param k: As description *return: The index after partition */ public int partitionArray(int[] nums, int k) { if(nums == null || nums.length == 0){ return 0; } int left = 0, right = nums.length - 1; while (left <= right) { while (left <= right && nums[left] < k) { left++; } while (left <= right && nums[right] >= k) { right--; } if (left <= right) { int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; left++; right--; } } return left; } }

Kth Smallest Numbers in Unsorted Array

cs3k.com

Find the kth smallest numbers in an unsorted integer array.

```java
class Solution {
    /*
     * @param k an integer
     * @param nums an integer array
     * @return kth smallest element
     */
    public int kthSmallest(int k, int[] nums) { // write your code here return quickSelect(nums, 0, nums.length - 1, k - 1); } public int quickSelect(int[] A, int start, int end , int k) { if (start == end) return A[start]; int left = start, right = end; int pivot = A[(start + end) / 2]; while (left <= right) { while (left <= right && A[left] < pivot) { left++; } while (left <= right && A[right] > pivot) { right--; } if (left <= right) { int temp = A[left]; A[left] = A[right]; A[right] = temp; left++; right--; } } if (right >= k && start <= right) return quickSelect(A, start, right, k); else if (left <= k && left <= end) return quickSelect(A, left, end, k); else return A[k]; } }; ```

Partition Array by Odd and Even

Partition an integers array into odd number first and even number second.

Interleaving Positive and Negative Numbers

cs3k.com

Given an array with positive and negative integers. Re-range it to interleaving with positive and negative integers.

Sort Letters by Case

Given a string which contains only letters. Sort it by lower case first and upper case second.

這三道題是類似的, 就是先把正的和負的分左右(奇數和偶數分左右), 再交替交換

其中要說明:

  1. 快排不是穩定排序, 1 1’ 2 可能變成 1’ 1 2

     

  2. merge sort歸併是穩定排序, 但是需要額外O(n)的空間

Sort Colors

cs3k.com

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

solution 1. 兩次partition

分0 1 2 可以先把0和1 2 分開

再分開1 和2, 兩次partition

solution 2. 三個指標

三個指標l, r, i

i指標, 從左到右

遇到0: i和l換, 左邊擴大1

遇到2: i和r換, 右邊擴大1

遇到0: 接著走,不做處理

public class Solution {
    public void sortColors(int[] a) { if (a == null || a.length <= 1) { return; } int pl = 0; int pr = a.length - 1; int i = 0; while (i <= pr) { if (a[i] == 0) { swap(a, pl, i); pl++; i++; } else if(a[i] == 1) { i++; } else { swap(a, pr, i); pr--; } } } private void swap(int[] a, int i, int j) { int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } }

Sort Colors II

Given an array of n objects with k different colors (numbered from 1 to k), sort them so that objects of the same color are adjacent, with the colors in the order 1, 2, … k.

科普幾個排序名詞

rainbow sort: 彩虹排序

counting sort: 計數排序

radix sort: 基數排序

基於比較的排序, 最快只能nlogn

這道題時間複雜度:

k = n 是 nlogn

k = 1 是 n

k = 2 是 n

k = 3 是 2*n

所以只能nlogk了

帶log的的, 怎麼把k的問題變為2/k的問題, 及怎麼把顏色範圍縮小一半

enter image description here

other sort

睡眠排序

麵條排序

猴子排序

ps: 寫程式是規定一個事情, 後面不破壞這個事情

Quick Select

cs3k.com

kth largest element

用快排的話, 需要O(nlogn)的時間, 如果需要更快的話, 嗯…

class Solution {
    /*
     * @param k : description of k
     * @param nums : array of nums
     * @return: description of return
     */
    public int kthLargestElement(int k, int[] nums) { // write your code here if (nums == null || nums.length == 0) { return 0; } if (k <= 0) { return 0; } return helper(nums, 0, nums.length - 1, nums.length - k + 1); } public int helper(int[] nums, int l, int r, int k) { if (l == r) { return nums[l]; } int position = partition(nums, l, r); if (position + 1 == k) { return nums[position]; } else if (position + 1 < k) { return helper(nums, position + 1, r, k); } else { return helper(nums, l, position - 1, k); } } public int partition(int[] nums, int l, int r) { // 初始化左右指標和pivot int left = l, right = r; int pivot = nums[left]; // 進行partition while (left < right) { while (left < right && nums[right] >= pivot) { right--; } nums[left] = nums[right]; while (left < right && nums[left] <= pivot) { left++; } nums[right] = nums[left]; } // 返還pivot點到數組裡面 nums[left] = pivot; return left; } };

T(n)  = T(2/n)  + O(n)

所以時間複雜度為:  n + n/2 + … + 1 ~2n

所以時間複雜度為O(n)