-- word search
>> 题目:给定一个二维数组和一个字符串,判断一个字符串是不是可以由二维数组中的相邻字母组成,相邻是指横向或纵向,数组中的每个字母只能使用一次。
>> 解题思路:首先找到字符串首字母在数组中的位置,然后依次遍历。问题1:如果一次没找到,应该重新找起始位置;问题2:每个点只能访问一次,如果重新找需要将访问次数清0.
-
public boolean exist(char[][] board, String word) {
-
if (word == null || word.length() == 0)
-
return true;
-
if (board == null || board.length == 0 || board[0].length == 0)
-
return false;
-
boolean[][] used = new boolean[board.length][board[0].length];
-
for (int i = 0; i < board.length; i++) {
-
for (int j = 0; j < board[0].length; j++) {
-
if (search(board, word, 0, i, j, used))
-
return true;
-
}
-
}
-
return false;
-
}
-
-
private boolean search(char[][] board, String word, int index, int i,
-
int j, boolean[][] used) {
-
if (index == word.length())
-
return true;
-
if (i < 0 || j < 0 || i >= board.length || j >= board[0].length
-
|| used[i][j] || board[i][j] != word.charAt(index))
-
return false;
-
used[i][j] = true;
-
boolean res = search(board, word, index + 1, i - 1, j, used)
-
|| search(board, word, index + 1, i + 1, j, used)
-
|| search(board, word, index + 1, i, j - 1, used)
-
|| search(board, word, index + 1, i, j + 1, used);
-
used[i][j] = false;
-
return res;
-
}
-- word latter
>> 题目:给定两个单词和一个词典,输出从单词1到单词2的最短路径长度
>> 解题思路:其实就是广度优先搜索就ok了,但是有一些细节需要处理,比如每一层可能会出现多个一样的,不应该将其放入队列
-
public int ladderLength(String start, String end, Set<String> dict) {
-
// special
-
if (start.equals(end)) {
-
return 0;
-
}
-
-
// define
-
Queue<String> visiting, nextVisiting, tempQ;
-
Set<String> visited;
-
char c;
-
int depth;
-
-
// init
-
visited = new HashSet<String>();
-
visiting = new LinkedList<String>();
-
nextVisiting = new LinkedList<String>();
-
c = 'a';
-
depth = 1;
-
-
// cal
-
visiting.add(start);
-
visited.add(start);
-
while (!visiting.isEmpty()) {
-
String item = visiting.poll();
-
-
if (item.equals(end)) {
-
return depth;
-
}
-
-
char []cs = item.toCharArray();
-
for (int i = 0; i < item.length(); i++) {
-
for (c = 'a'; c < 'z'; c++) {
-
if (item.charAt(i) == c) {
-
continue;
-
}
-
cs[i] = c;
-
String temp = new String(cs);
-
-
if (dict.contains(temp) && !visited.contains(temp)) {
-
nextVisiting.add(temp);
-
visited.add(temp);
-
}
-
}
-
cs[i] = item.charAt(i);
-
}
-
-
if (visiting.isEmpty()) {
-
depth++;
-
tempQ = nextVisiting;
-
nextVisiting = visiting;
-
visiting = tempQ;
-
}
-
}
-
-
// ret
-
return 0;
-
}
-- word latter II
>> 题目:给定两个单词和一个词典,输出所有可能从单词1到单词2的路径
-
private void bfs(String start, String end, Set<String> dict, Map<String, Integer> depthMap) {
-
// define
-
Queue<String> visiting, nextVisiting, tempQ;
-
Set<String> visited;
-
char c = 'a';
-
int depth;
-
-
// init
-
visiting = new LinkedList<String>();
-
nextVisiting = new LinkedList<String>();
-
visited = new HashSet<String>();
-
depth = 2;
-
-
// cal
-
visited.add(start);
-
visiting.add(start);
-
depthMap.put(start, 1);
-
while (!visiting.isEmpty()) {
-
String item = visiting.poll();
-
-
if (item.equals(end)) {
-
return;
-
}
-
-
char []cs = item.toCharArray();
-
for (int i = 0; i < item.length(); i++) {
-
for (c = 'a'; c <= 'z'; c++) {
-
if (cs[i] == c) {
-
continue;
-
}
-
cs[i] = c;
-
String temp = new String(cs);
-
if (dict.contains(temp) && !visited.contains(temp)) {
-
nextVisiting.add(temp);
-
visited.add(temp);
-
depthMap.put(temp, depth);
-
}
-
cs[i] = item.charAt(i);
-
}
-
}
-
-
if (visiting.isEmpty()) {
-
tempQ = nextVisiting;
-
nextVisiting = visiting;
-
visiting = tempQ;
-
depth++;
-
}
-
}
-
}
-
-
private void dfs(String start, String end, Set<String> dict, Map<String, Integer> depthMap, List<String> path, List<List<String>> result) {
-
// define
-
List<String> newPath;
-
char c = 'a';
-
int depth;
-
-
// init
-
-
//special
-
if (start.equals(end)) {
-
path.add(end);
-
result.add(path);
-
return;
-
}
-
if (!depthMap.containsKey(start)) {
-
return;
-
}
-
path.add(start);
-
depth = depthMap.get(start);
-
char []cs = start.toCharArray();
-
for (int i = 0; i < start.length(); i++) {
-
for (c = 'a'; c <= 'z'; c++) {
-
if (c == cs[i]) {
-
continue;
-
}
-
cs[i] = c;
-
-
String temp = new String(cs);
-
if (depthMap.containsKey(temp) && depthMap.get(temp) == depth + 1) {
-
newPath = new ArrayList<String>(path);
-
dfs(temp, end, dict, depthMap, newPath, result);
-
}
-
cs[i] = start.charAt(i);
-
}
-
}
-
-
}
-
-
public List<List<String>> findLadders(String start, String end, Set<String> dict) {
-
// define
-
List<List<String>> result = new ArrayList<List<String>>();
-
Map<String, Integer> depthMap = new HashMap<String, Integer>();
-
List<String> path = new ArrayList<String>();
-
-
// special
-
if (start == null || end == null) {
-
return result;
-
}
-
-
// init
-
-
// cal
-
bfs(start, end, dict, depthMap);
-
dfs(start, end, dict, depthMap, path, result);
-
-
// ret
-
return result;
-
}
-- unique path
>> 题目:从二维数组的左上角到右下角一共有多少种可能的路径
>> 解题思路:实现最简单的,暴力解法,但是时间复杂度较高 ;使用动态规划,降低时间复杂度到m * n;
-
// 暴力解法
-
public int uniquePaths(int m, int n) {
-
if (m == 1 || n == 1)
-
return 1;
-
return uniquePaths(m - 1, n) + uniquePaths(m, n - 1);
-
}
-
public int uniquePaths(int m, int n)
-
{
-
if (m == 1 || n == 1) {
-
return 1;
-
}
-
int [][]A = new int[m][n];
-
for (int i = 0; i < m; i++) {
-
A[i][0] = 1;
-
}
-
for (int j = 0; j < n; j++) {
-
A[0][j] = 1;
-
}
-
-
for (int i = 1; i < m; i++) {
-
for (int j = 1; j < n; j++) {
-
A[i][j] = A[i - 1][j] + A[i][j - 1];
-
}
-
}
-
return A[m - 1][n - 1];
-
-
}
-- unique pathII
>> 题目:现在增加障碍
>> 解题思路:对于障碍位置特殊处理,但是要注意对边的处理和非边的处理是不一样的。
-
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
-
int m = obstacleGrid.length;
-
if (m == 0) return 0;
-
int n = obstacleGrid[0].length;
-
if (n == 0) return 0;
-
int [][]A = new int[m][n];
-
boolean flag = true;
-
for (int i = 0; i < m; i++) {
-
if (flag) {
-
if (obstacleGrid[i][0] == 1) {
-
A[i][0] = 0;
-
flag = false;
-
} else {
-
A[i][0] = 1;
-
}
-
} else {
-
A[i][0] = 0;
-
}
-
}
-
flag = true;
-
for (int j = 0; j < n; j++) {
-
if (flag) {
-
if (obstacleGrid[0][j] == 1) {
-
A[0][j] = 0;
-
flag = false;
-
} else {
-
A[0][j] = 1;
-
}
-
} else {
-
A[0][j] = 0;
-
}
-
}
-
for (int i = 1; i < m; i++) {
-
for (int j = 1; j < n; j++) {
-
if (obstacleGrid[i][j] == 1) {
-
A[i][j] = 0;
-
} else {
-
A[i][j] = A[i - 1][j] + A[i][j - 1];
-
}
-
}
-
}
-
return A[m - 1][n - 1];
-
}
-- two sum
>> 题目:给定一个数组,和一个数,假定肯定可以找到两个数,使其和为给定的数,求出这两个数在数组中的index
>> 解题思路:首先将数组和index存入map,然后依次匹配,主要有重复问题,注意一个数字不能使用两次,就算数组中有两个一样的也可以使用下面的解法,因为map是唯一key模式,只会记录后一个。
-
public int[] twoSum(int[] numbers, int target) {
-
int []ret = new int[2];
-
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
-
for (int i = 0; i < numbers.length; i++) {
-
map.put(numbers[i], i + 1);
-
}
-
for (int i = 0; i < numbers.length; i++) {
-
if (map.containsKey(target - numbers[i]) && map.get(target - numbers[i]) != i + 1) {
-
ret[0] = i + 1;
-
ret[1] = map.get(target - numbers[i]);
-
break;
-
}
-
}
-
return ret;
-
}
-- triangle
>> 题目:给定一个三角形, 找出从上到下由相邻数组成的路径上点和的最小值
-- trapping raining water
>> 题目:给定一个数组,每个元素代表其高度,计算最多可以乘多少水。
>> 解题思路:这道题的解法是基于单调栈(就是栈中的数据按从小到大或从大到小),然后入栈前对于栈顶元素进行判断,是否小于等于自己,计算响应的有效面积,中间计算过的小面积应该删掉。
-
public int trap(int[] A) {
-
int sum = 0, midHeight = 0, index = 0;
-
Stack<Integer> posStack = new Stack<Integer>();
-
-
for (int i = 0; i < A.length; i++) {
-
while (!posStack.isEmpty()) {
-
index = posStack.peek();
-
int temp = A[i] < A[index] ? A[i] : A[index];
-
// 减去midHeight 就是去掉已经算过的
-
sum += (temp - midHeight) * (i - index - 1);
-
midHeight = A[index];
-
if (A[i] >= A[index]) {
-
posStack.pop();
-
} else {
-
break;
-
}
-
}
-
posStack.push(i);
-
}
-
-
return sum;
-
}
-- subset
>> 题目:给定一个不同数的集合,请求所有可能的子集
>> 解题思路:遍历根据放入和不放入两种情况进行深度优先遍历。
-- subset II
>> 题目:给定一个可能包含重复数的集合,求出所有的子集
>> 解题思路:首先先排序,然后遍历的时候也会稍后不同,如果全部都是不一样的,挨个遍历每个字母就ok了。但是如果有了重复的,每一次会依次选遍历节点后的每个节点作为每个集合中遍历节点的后续节点,这样对于每一层的遍历就可以去掉相同的就ok了。
-- spiral matrix
>> 题目:给定一个矩阵,输出它的绕圈遍历顺序
>> 解题思路:略简单,就是遍历。
-- spiral matrix2
>> 题目:给定一个正数n,输出n^2个数按spiral顺序的matrix
>> 解题思路:类似于1
-- sort colors
>> 题目:给一个数组,标记为不同数组,进行排序,使相同数字相邻。
>> 解题思路:包含重复数的排序。
-- set matrix zeroes
>> 题目:给定一个数组,如果某一个元素为0, 两个将其所在的行和列都设置为0
>> 解题思路:首先遍历一遍,记录需要置位的行和列,然后遍历zhi'wei
-- search insert position
>> 题目:给定一个排好序数组和一个数字,如果存在,找出其位置否则找出其插入位置,无重复
>> 解题思路:暴力搜索,加快速度可以二分查找
-- search in rotated sorted array
>> 题目:数组中的某几位被循环移位,查找
>> 解题思路: 暴力搜索,加快速度可以二分查找
-- search in rotated sorted array II
>> 题目:数组中的某几位被循环移位,查找
>> 解题思路: 暴力搜索,加快速度可以二分查找
-- Search for a Range
>> 题目:从一个包含重复的数组中找到某个数的范围
>> 解题思路:二分查找
-
public int[] searchRange(int[] A, int target) {
-
-
int mid = 0, start = 0, end = A.length;
-
int []index = new int[2];
-
for ( ; start >= end; ) {
-
mid = start + (end - start) / 2;
-
if (target == A[mid]) {
-
break;
-
} else if (target < A[mid]) {
-
end = mid - 1;
-
} else {
-
start = mid + 1;
-
}
-
}
-
if (target == A[mid]) {
-
index[0] = mid;
-
index[1] = mid;
-
for (int i = mid - 1; i > -1; i--) {
-
if (target == A[i]) {
-
index[0] = i;
-
} else {
-
break;
-
}
-
}
-
for (int i = mid + 1; i < A.length; i++) {
-
if (target == A[i]) {
-
index[1] = i;
-
} else {
-
break;
-
}
-
}
-
} else {
-
index[0] = -1;
-
index[1] = -1;
-
}
-
-
-
-
return index;
-
}
-- Search a 2D Matrix
>> 题目:给定一个matrix,求该matrix是否每一行是增序的且后一行的首大于上一行的尾
>> 解题思路:遍历
-- Rotate Image
>> 题目:给定各一个matrix,转90度
>> 解题思路:可以通过两步对换得到
-- Remove Elemet
>> 题目:从数组中移除元素,返回长度
>> 解题思路:遍历,移除以后需要调整后续的位置。
-- Remove Duplicates from Sorted Array
>> 题目:从有序数组中删除重复元素,只留其中一个
>> 解题思路:遍历,每次删除元素后,调整后续的位置。
-- Remove Duplicates from Sorted Array II
>> 题目:从有序数组中删除超过两次重复元素,只留其中两次
>> 解题思路:遍历,记录次数,每次删除元素后,调整后续的位置。
-- Plus One
>> 题目:给数加1 ,但是每一位站数组中的一个元素
>> 解题思路:注意进位
-- Pascal's Triangle
>> 题目:构造二维数组
>> 解题思路:注意边界问题
--
Pascal's Triangle II
>> 题目:构造二维数组,输出其中的某一行
>> 解题思路:注意边界问题
-- Next Permutation
>> 题目:返回一个数组的下一个字典序
>> 解题思路: 从后往前找到第一个降序的位置,然后将这个位置与其后第一个比他大的交换,将这个位置后的排序(升序)
-
void nextPermutation(vector<int> &num) {
-
int i = num.size() - 1, tmp = 0, idx = 0;
-
for ( ; i > 0; i--) {
-
if (num[i] > num[i - 1]) {
-
idx = i - 1;
-
for (i = num.size() - 1; ; i--) {
-
if (num[i] > num[idx]) break;
-
}
-
tmp = num[idx];
-
num[idx] = num[i];
-
num[i] = tmp;
-
sort(num.begin() + idx + 1, num.end());
-
return;
-
}
-
}
-
if (i == 0) {
-
sort(num.begin(), num.end());
-
}
-
}
阅读(1431) | 评论(0) | 转发(0) |