Rotate String
- 题目:
- 思路:
class Solution {
public boolean rotateString(String A, String B) {
if (A == null || B == null || A.length() != B.length()) {
return false;
}
String C = B + B;
return C.indexOf(A) == -1 ? false : true;
}
}
Closest Two Sum max average sum subetree 两种版本: 1.二叉树 2.多个子节点 merge two Sorted List 一排数据中心,每个数据中心链接有cost, 求将所有数据中心连接起来并且cost最小的方式 Leetcode 819 Leetcode 973 K Closest Points to Origin
- 问题: 给出一个二维数组表示一些点的坐标和一个值K,求出距离原点(0,0)最近的K个点,并放在二维数组中返回
- 思路: 维护一个size 为K的最大堆,用来更新距离前k小的点
PriorityQueue<Integer> pq = new PriorityQueue(k, new Comparator<Integer>(public int compare(int a, int b) {return b - a;})))
compare是声明的方法
PriorityQueue<Point> pq = new PriorityQueue<Point> (k, new Comparator<Point> () {
@Override
public int compare(Point a, Point b) {
return (int) (getDistance(a, origin) - getDistance(b, origin));
}
});
// 实现最大堆的代码需要记忆
class Solution {
public int[][] kClosest(int[][] points, int K) {
Queue<int[]> queue=new PriorityQueue<>((a, b) -> (a[0]*a[0]+a[1]*a[1])-(b[0]*b[0]+b[1]*b[1]));
int[][] res=new int[K][2];
int index=0;
for(int[] arr:points) {
queue.add(arr);
}
while(index<K) {
res[index]=queue.poll();
index++;
}
return res;
}
}
LintCode High Five
public class Solution {
/**
* @param results a list of <student_id, score>
* @return find the average of 5 highest scores for each person
* Map<Integer, Double> (student_id, average_score)
*/
public Map<Integer, Double> highFive(Record[] results) {
Map<Integer, Double> answer = new HashMap<Integer, Double>();
Map<Integer, PriorityQueue<Integer>> hash = new HashMap<Integer, PriorityQueue<Integer>>();
for (Record r : results) {
if (!hash.containsKey(r.id)){
hash.put(r.id, new PriorityQueue<Integer>());
}
PriorityQueue<Integer> pq=hash.get(r.id);
if (pq.size() < 5) {
pq.add(r.score);
} else {
if (pq.peek() < r.score){
pq.poll();
pq.add(r.score);
}
}
}
for (Map.Entry<Integer, PriorityQueue<Integer>> entry : hash.entrySet()) {
int id = entry.getKey();
PriorityQueue<Integer> scores = entry.getValue();
double average = 0;
for (int i = 0; i < 5; ++i)
average += scores.poll();
average /= 5.0;
answer.put(id, average);
}
return answer;
}
}
K - 1 Substring
Valid Parenthesis
[LintCode] 597 Subtree with Maximum Average
- 题目: 给出一棵二叉树,找出其中平均值最大的子树节点
- 思路: 新写一个
ResultType
类来将保存node,size子树节点个数,sum(子树值的总和) - 变形: 给出多叉树,或者只能返回非叶节点
public class Solution {
/**
* @param root: the root of binary tree
* @return: the root of the maximum average of subtree
*/
private class Result {
private int sum;
private int size;
private TreeNode node;
public Result(int sum, int size, TreeNode node) {
this.sum = sum;
this.size = size;
this.node = node;
}
}
private Result currMax = null;
public TreeNode findSubtree2(TreeNode root) {
// write your code here
if (root == null) {
return null;
}
helper(root);
return currMax.node;
}
private Result helper(TreeNode node) {
if (node == null) {
return new Result(0,0,null);
}
Result left = helper(node.left);
Result right = helper(node.right);
Result res = new Result(
left.sum + right.sum + node.val,
left.size + right.size + 1,
node);
if (currMax == null || res.sum * currMax.size > res.size * currMax.sum) {
currMax = res;
}
return res;
}
}
public class Solution {
class Result {
CategoryNode node;
int sum;
int size;
public Result(CategoryNode node, int sum, int size) {
this.node = node;
this.sum = sum;
this.size = size;
}
}
private Result currMax = null;
public CategoryNode getMostPupularNode(CategoryNode rootCategory) {
if (rootCategory == null) {
return null;
}
Result rootRes = helper(rootCategory);
return res.node;
}
public Result helper(CategoryNode root) {
if (root == null) {
return new Result(null, 0, 0);
}
ArrayList<Result> results = new ArrayList<Result>();
for (CategoryNode n : root.subCategoryNode) {
results.add(helper(n));
}
int childSum = 0;
int childSize = 0;
for (Result r : results) {
childSum += r.sum;
childSize += r.size;
}
Result c = new Result(root)
}
}
819. Most Common Word
- 题目: 给出一个长的String段落和一个词汇黑名单,找出不在禁用词当中的频率最高的词
- 思路: 先切割段落,然后统计词频,找出不在黑名单中的单词 统计词频是用HashMap. 切割段落的时候要同时用到空格和逗号两个分隔符?
// 直接一句话搞定 两种情况 在map中的+1 和 不在map中的直接新建为1
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
class Solution {
public String mostCommonWord(String paragraph, String[] banned) {
if (paragraph == null || paragraph.length() == 0) {
return "";
}
HashMap<String, Integer> map = new HashMap<>();
// 使用穷举法进行段落分割 `+`加号在这里表示出现次数为多次
String[] words = paragraph.toLowerCase().split("[ ?!;,.']+");
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
for (String word : banned) {
if (map.containsKey(word)) {
map.remove(word);
}
}
String res = null;
for (String key : map.keySet()) {
if (res == null || map.get(key) > map.get(res)) {
res = key;
System.out.println(key + "" + map.get(key));
}
}
return res;
}
}
双指针类
所有的双指针类型的题目都是要维持指针区间,一定会有多个循环条件,已经指针的更新条件的变化,注意指针移动变化之后的变量与不变量 两个指针更新方式 可以通过while loop或者 for loop
- 同向双指针
- Longest Substring with At Most Two Distinct Characters
- 题目: 找出只有两个distinct字符的最长子串
- 思路: 用count[]数组来记录出现次数, 用distinctCount变量记录出现的distinct字符数
class Solution { public int lengthOfLongestSubstringTwoDistinct(String s) { if (s == null || s.length() == 0) { return 0; } int maxSize = 0; int size = s.length(); int[] count = new int[128]; int distinctCount = 0; int j = 0; for (int i = 0; i < size; i++) { while (j < size) { if (distinctCount == 2 && count[s.charAt(j)] == 0) { break; } if (count[s.charAt(j)] == 0) { distinctCount++; } count[s.charAt(j++)]++; } maxSize = Math.max(maxSize, j - i); count[s.charAt(i)]--; if (count[s.charAt(i)] == 0) { distinctCount--; } } return maxSize; }
} ```
- Longest Substring with At Most K Distinct Characters
- 相向双指针
LintCode 533 [Two Sum Closest]
- 对撞型双指针
- 问题: 找到不大于k的最接近的一组数字
- 思路: 先排序
public int twoSumClosest(int[] nums, int target) {
if (nums == null || nums.length < 2) {
return -1;
}
Arrays.sort(nums);
int left = 0;
int right = nums.length - 1;
int diff = Integer.MAX_VALUE;
while (left < right) {
if (nums[left] + nums[right] < target) {
diff = Math.min(diff, target - nums[left] - nums[right]);
left++;
}
else {
diff = Math.min(diff, nums[left] + nums[right] - target);
right--;
}
}
return diff;
}
Shortest path in a Binary Maze
- https://en.wikipedia.org/wiki/Lee_algorithm Lee Algorithm:
- initialize
- wave expansion: repeat mark all unlabeled neighbors of points marked with i with i + 1
- go to target point -> repeat go to next node that has a lower mark than the current node
- clear marks

Reorder
字符的字典序比较 dictionary order alphabetical order
"ah1".compareTo("ahb")
比较的就是两个字符的ASCII差值,如果小于零说明第一个字符串小于第二个字符串
64. Minimum Path Sum
- 题目: 给出一个m * n的方格,找出一条从左上到右下和最小的路径, 只可以向下或向右移动
- 思路: 局部最小和全局最小之间的关系?全局最小也是局部最小
public class Solution {
public int minPathSum(int[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
int M = grid.length;
int N = grid[0].length;
int[][] sum = new int[M][N];
sum[0][0] = grid[0][0];
for (int i = 1; i < M; i++) {
sum[i][0] = sum[i - 1][0] + grid[i][0];
}
for (int i = 1; i < N; i++) {
sum[0][i] = sum[0][i - 1] + grid[0][i];
}
for (int i = 1; i < M; i++) {
for (int j = 1; j < N; j++) {
sum[i][j] = Math.min(sum[i - 1][j], sum[i][j - 1]) + grid[i][j];
}
}
return sum[M - 1][N - 1];
}
}
K - 1 distinct characters

- 问题: 给一个字符串和一个整数数字
- 输入: inputString = "awaglk" num = 4
- 输出: ["awag"]
- 思路: 双指针, 1个指针固定头, 另一个直接
import java.util.*;
public class Solution {
public static List<String> Kdistinct(String s, int k) {
List<String> res = new ArrayList<>();
if (s == null || s.length() == 0) {
return res;
}
int size = s.length();
int[] count = new int[128];
int distinctCount = 0;
for (int i = 0; i < size; i++) {
Arrays.fill(count, 0);
distinctCount = 0;
for (int j = i; j < size; j++) {
if (count[s.charAt(j)] == 0) {
distinctCount++;
}
System.out.println("i: " + i);
System.out.println("j: " + j);
System.out.println("distinct: " + distinctCount);
if (distinctCount == k - 1 && j - i + 1== k) {
res.add(s.substring(i, j + 1));
}
count[s.charAt(j)]++;
}
}
return res;
}
public static void main(String[] args) {
int n = 4;
String input = "awagkmg";
List<String> res = Kdistinct(input, n);
for (String s : res) {
System.out.println(s);
}
}
}
K-Substring with K different characters
public class Solution {
/**
* @param stringIn: The original string.
* @param K: The length of substrings.
* @return: return the count of substring of length K and exactly K distinct characters.
*/
public int KSubstring(String stringIn, int K) {
if (stringIn == null || stringIn.length() == 0 || K <= 0) {
return 0;
}
int count = 0;
HashMap<Character, Integer> charMap = new HashMap<>();
HashSet<String> resultSet = new HashSet<String>();
int len = stringIn.length();
int j = 0;
for (int i = 0; i < len; i++) {
while (j < len && charMap.size() < K) {
char c = stringIn.charAt(j);
if (charMap.containsKey(c)) {
break;
}
charMap.put(c, 1);
j++;
// size == k是保证了子串长度为k
if (charMap.size() == K) {
resultSet.add(stringIn.substring(i, j));
}
}
charMap.remove(stringIn.charAt(i));
}
return resultSet.size();
}
}
937. Reorder Log Files
- 问题: 本质上是字符串的字典序比较 分为三种情况讨论 identifier > letter > digit
- 思路: 自定义一个Comparator进行比较
class Solution {
public String[] reorderLogFiles(String[] logs) {
Comparator<String> com = new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
int s1Start = s1.indexOf(' ');
int s2Start = s2.indexOf(' ');
char s1Char = s1.charAt(s1Start + 1);
char s2Char = s2.charAt(s2Start + 1);
if (s1Char <= '9') {
if (s2Char <= '9') { // natural order
return 0;
} else { // s1 is digit-log, s2 is letter-log
return 1;
}
}
if (s2Char <= '9') { // s2 is digit-log, s1 is letter-log
return -1;
}
// s1 and s2 are both letter-log
int preCompute = s1.substring(s1Start + 1).compareTo(s2.substring(s2Start + 1));
// ignore identifier letter-logs are ordered tie
if (preCompute == 0) {
return s1.substring(0, s1Start).compareTo(s2.substring(0, s2Start));
}
return preCompute;
}
};
Arrays.sort(logs, com);
return logs;
}
}