一维数组
1. 找递增或递减序列
while(end<n && ratings[end]>ratings[end-1])
{
candies[end] = candies[end-1] + 1;
end++;
}
n个加油站,组成一圈,每个点有加油g[i],每两个点之间耗油c[i]。
判断能不能从一个点出发绕一圈?只要g[i]之和大于等于c[i]之和即可。
找到一个合理的起点。计算v[i] = g[i]-c[i]。从某一点出发向前走,记录当前经过的v[i]和,如果大于0,则继续向前,如果小于0,则将出发点后移。直到绕成一圈。
3. 在一个数组中找出最长的连续序列(即数组中的多个元素构成序列,序列中元素值是连续的)Longest Consecutive Sequence
对于当前的元素x,分别寻找x-1,x-2...在不在数组中,直到找到某个值不在数组中为止。同理,寻找x+1,x+2...在不在数组中,直到找到某个值不在数组中为止。在找到这些值的同时可以将它们从数组中删除,避免下次重复寻找这些数组的左右连续数值。
在数组中寻找某个值的方式,如果使用hash(在C++中是unordered_set),那么每次寻找的时间代价为O(1)。
4. 给定一个start单词和一个end单词,还有一个词典。求一个从start到end的变换,变换的每一步只能改变单词中的一个字母,同时保证中间单词都在词典中。Word Ladder
宽度优先遍历。给定一个当前的单词,枚举它的每一位,枚举每一位可能的变换(25种),将变换得到的新词放到宽度优先的队列中。在队列中用” “分割每一层的单词。变化的次数实际上就是当前所在的层数。
5. 买股票问题,利益最大化。Best Time to Buy and Sell Stock I II III
1) 如果只能买一次,卖一次,怎么选择。
对于第i天,计算从第i天到第n-1天中价格最高的那天的价格highest[i],这个计算是O(n)的。
然后依次计算highest[i]-prices[i]的最大值。
2) 如果可以买卖任意多次。
找全部递增序列,在每个起始点买入,每个结束点卖出。
3) 如果只能买卖两次。
递归的方法:枚举分界的那一天k,计算第1到k天买卖一次的最大收益,和第k+1到n天买卖一次的最大收益。求得两次收益和最大的那一分界天。会超时。
动态规划的方法:计算left[i]表示第1到第i天买卖一次的最大收益,right[i]表示第i天到第n天买卖一次的最大收益。求得left[i]+right[i]最大的那一个。
6. Search in Rotated Sorted Array I II
二分的方式查找。
通过比较a[mid]与a[left],a[right]的值,可以确定左半边和右半边一个有序,一个无序。
二维数组(矩阵)
1. Surrounded Regions
从二维数组的最外面一层的每个单元开始,先判断位置是否出界,如果出界则结束标记直接返回。如果没出界,则先判断当前单元的值,如果不是O则结束标记直接返回。如果满足条件则将其标记为N,再递归的判断其相邻的(最多)四个结点的值。
递归函数为:dfs
void dfs(vector<vector<char>> &board, int h, int w)
{
int height = board.size();
int width = board[0].size();
// if out of range, return
if(h<0 || h>=height || w<0 || w>=width)
return;
// if the region is not 'o', return
if(board[h][w] != 'O')
return;
// mark the original region 'O' to 'N'
board[h][w] = 'N';
// dfs, mark surrounding regions recursively
dfs(board, h-1, w);
dfs(board, h+1, w);
dfs(board, h, w-1);
dfs(board, h, w+1);
}
2. Word Search
在矩阵中枚举单词的起始位置,调用递归函数。
递归函数的参数有单词的下表begin,在矩阵中的位置[i,j],这次枚举的visited矩阵(记录每个单元是否被访问过)。
如果begin等于n,说明已经找到单词。
如果begin不等于n,如果矩阵位置出界则返回false。如果当前位置被访问过或者当前位置的字母与单词中的字母不同,则返回false。
否则将当前位置标记成visited。然后递归的调用四个方向的递归函数,如果其中任意一个返回false,则当前函数返回false。
如果没有一个方向成功的,则当前位置被置为unvisited,代表不能选择当前位置,相当于回溯!然后返回false。
这样可以保证当前visited中为true的,就是当前这次查找中被访问过的、部分匹配了的单元。
bool find(vector<vector<char>> &board, int i, int j, string word, int begin, bool **visited)
{
int n = word.length();
int height = board.size();
int width = board[0].size();
// find!
if(begin == n)
return true;
// out of matrix
if(i >= height || i < 0)
return false;
if(j >= width || j < 0)
return false;
// has been visited already or not match
if(visited[i][j] == true || word[begin] != board[i][j])
return false;
// visit this cell
visited[i][j] = true;
// visit its neighbors recursively
if(find(board, i-1, j, word, begin+1, visited) || find(board, i+1, j, word, begin+1, visited) || find(board, i, j-1, word, begin+1, visited) || find(board, i, j+1, word, begin+1, visited))
return true;
// cancel visit this cell!!
visited[i][j] = false;
return false;
}