九章算法笔记 7.两根指针 Two Pointers

大纲 算法视频QQ_1603159172

  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 

算法视频QQ_1603159172

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

算法视频QQ_1603159172

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 

算法视频QQ_1603159172

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 

算法视频QQ_1603159172

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 

算法视频QQ_1603159172

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 

算法视频QQ_1603159172

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

算法视频QQ_1603159172

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

算法视频QQ_1603159172

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

算法视频QQ_1603159172

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

算法视频QQ_1603159172

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)

posted @ 2018-11-02 12:52  pkuhjs  阅读(359)  评论(0编辑  收藏  举报