outline
- 一个数组,从两边往中间移动(对撞型)
- 一个数组,同时向前移动(前向型)
- 两个数组两根指针(并行型)
1.对撞型或相会型
leetcode 11.Container With Most Water
题目
Given n non-negative integers a1, a2, …, an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.
分析
灌水问题,从两边向内灌水,所以初始两个指针ij一头一尾,此时能够容纳的水量是i和j中比较高度的柱子高度*ij两个柱子之间的距离:
max(height[i] , height[j]) * (j - i)
然后考虑将柱子向内移动,其实我们只需要移动比较矮的柱子,因为如果移动长的一边的柱子,根据上面的公式,j-i会变短,max(height[i] , height[j])可能变小可能不变,所以总的水量不会增加,所以我们只有移动短的柱子,才有可能会遇到更高的柱子,使得水量增大。
这样一来,每次选取较短的柱子向内移动,时间复杂度为
代码
|
Quick select — Kth Largest Element in an Array
问题
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given[3,2,1,5,6,4]
and k = 2, return 5.
在一组数字中找到第K大的数字
思路
方法一:可以用堆,维护一个大小为K的堆,将数字依次加入堆,找到第k大,时间复杂度
方法二:quick select,基于quick sort的思想
- 每次在数组中随机选取一个数组作为pivort,这里面随机选取,经过大量的验证,选取中间位置的数字作为pivot比较稳妥。
- 然后和快排一样,将比它小的放在它左边,比它大的放在右边,找到pivot的位置即是pivot的最终位置。
- 如果此时pivot的位置==k-1,找到了
- 如果此时pivot的位置 >k-1,只需在pivot左边寻找第k大
- 如果此时pivot的位置 <k-1,只需在pivot右边寻找第k-pivot大
这种方法的时间复杂度为
两种方法的比较:
代码
|
lintcode 399.Nuts & Bolts Problem
题目
给定一组 n 个不同大小的 nuts 和 n 个不同大小的 bolts。nuts 和 bolts 一一匹配。 不允许将 nut 之间互相比较,也不允许将 bolt 之间互相比较。也就是说,只许将 nut 与 bolt 进行比较, 或将 bolt 与 nut 进行比较。请比较 nut 与 bolt 的大小
样例
给出 nuts =
['ab','bc','dd','gg']
, bolts =['AB','GG', 'DD', 'BC']
你的程序应该找出bolts和nuts的匹配。
一组可能的返回结果是:
nuts =['ab','bc','dd','gg']
, bolts =['AB','BC','DD','GG']
分析
因为nuts和bolts两个数组在各自的内部不能互相比较,只能在两个数组之间的元素进行比较。所以这就需要利用一个array中的元素对另一个array进行partition,并反过来重复这一个过程,最终让两个array都满足comparator所定义的相同顺序。
代码
|
2.窗口类
Minimum Size Subarray Sum
题目
Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn’t one, return 0 instead.
For example, given the array
[2,3,1,2,4,3]
ands = 7
,
the subarray[4,3]
has the minimal length under the problem constraint.
返回数组中元素和>=s的最长子数组的长度
分析
两指针控制滑动窗口类问题,当窗口内元素和<s时右指针向右滑动,更新最大长度
当窗口内元素和>=s时,左指针向右滑动至<s,无需更新最大长度
代码
|
Longest Substring Without Repeating Characters
题目
Given a string, find the length of the longest substring without repeating characters.
Examples:
Given
"abcabcbb"
, the answer is"abc"
, which the length is 3.Given
"bbbbb"
, the answer is"b"
, with the length of 1.Given
"pwwkew"
, the answer is"wke"
, with the length of 3. Note that the answer must be a substring,"pwke"
is a subsequence and not a substring.
查找字符串中没有重复元素的最长子串
思路
记录窗口中出现过哪些字母,当遇到重复字母的时候窗口缩小
代码
|
Minimum Window Substring
题目
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
For example,
S ="ADOBECODEBANC"
T ="ABC"
Minimum window is
"BANC"
.
返回s中能够包含t的最短子串
思路
滑动窗口+hashtable的思想
首先需要两个hash表,一个存储t中的字母,一个存储s中子串的字母,还需要一个能够判别s中的子串是否能够包含t的函数。
然后两指针滑动窗口,右指针向右滑动,当滑窗中的子串能够包含t时,窗口缩小,左指针右移,更新最短窗口,直到窗口内子串不足以包含t中全部字母,此时右指针继续向后移动,重复上述过程。
代码
|
Longest Substring with At Most K Distinct Characters
题目
Given a string, find the length of the longest substring T that contains at most k distinct characters.
For example, Given s =
“eceba”
and k = 2,T is “ece” which its length is 3.
在字符串中找到一个子串,最多包含k个不同的字母,返回满足这样条件的子串的最大长度。
分析
还是滑窗+hash表
用hash表存储当前子串中字母,用charNum存储子串中的不同字母个数
- 当窗口内字母个数<=k时右指针向右滑动,扩大窗口,更新窗口大小
- 当窗口内字母个数>k时,左指针右移,缩小窗口,
代码
|
两个数组两个指针
最小差
题目
给定两个整数数组(第一个是数组
A
,第二个是数组B
),在数组 A 中取 A[i],数组 B 中取 B[j],A[i] 和 B[j]两者的差越小越好(|A[i] - B[j]|)。返回最小差。样例
给定数组 A =
[3,4,6,7]
, B =[2,3,8,9]
,返回0
。
给定两个数组,返回两个数组元素之间的最小差
分析
baseline:双层for循环,A中循环一遍B中循环一遍,计算每两个元素之间的差值取最小,时间复杂度:
优化:
先排序,排序之后遍历A中元素,用二分查找的思路在B中寻找与元素A[i]差值最小的元素,时间复杂度:
骚操作:
两指针ij分别指向AB,更新A[i]和B[j]的差值
当A[i]<B[j]时,i后移,反之j后移
代码
|
Smallest Range
题目
You have
k
lists of sorted integers in ascending order. Find the smallest range that includes at least one number from each of thek
lists.We define the range [a,b] is smaller than range [c,d] if
b-a < d-c
ora < c
ifb-a == d-c
.Example 1:
> Input:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]> Output: [20,24]> Explanation:> List 1: [4, 10, 15, 24,26], 24 is in range [20,24].> List 2: [0, 9, 12, 20], 20 is in range [20,24].> List 3: [5, 18, 22, 30], 22 is in range [20,24].>
给定k个数组,找到最短的区间,该区间需满足包含来自每个数组的至少一个元素
分析
k个数组k个指针,k个指针中的最大最小即是当前情况下的区间。
每次将值最小的指针向后移动,更新当前情况下的区间长度。
这里就需要找到哪个指针所指的值是最小的了,所以我们需要一个最小堆来维护k个指针中的最小值。
另外,我们还需要计算k个指针中的最大值,这个最大值用一个变量max维护就可以了,每次入堆的元素都跟当前max比较更新一下就好。
代码
|
Partition Labels
题目
A string
S
of lowercase letters is given. We want to partition this string into as many parts as possible so that each letter appears in at most one part, and return a list of integers representing the size of these parts.Example 1:
> Input: S = "ababcbacadefegdehijhklij"> Output: [9,7,8]> Explanation:> The partition is "ababcbaca", "defegde", "hijhklij".> This is a partition so that each letter appears in at most one part.> A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts.>
给定一个字符串,要求将字符串分割,保证每个字母只出现在一个子串中,最终返回分割的字符串长度
分析
|
代码
|