1091. Shortest Path in Binary Matrix

Given an n x n binary matrix grid, return the length of the shortest clear path in the matrix. If there is no clear path, return -1.

A clear path in a binary matrix is a path from the top-left cell (i.e., (0, 0)) to the bottom-right cell (i.e., (n - 1, n - 1)) such that:

All the visited cells of the path are 0.
All the adjacent cells of the path are 8-directionally connected (i.e., they are different and they share an edge or a corner).
The length of a clear path is the number of visited cells of this path.

由于不能重复搜索,且需要在搜索时将搜索过的位置改变,因此需要采用BFS逐一层级的搜索。
逐层级搜索并记录层级。最后返回层级+1即可。
(还有更快的优化算法A*)

整体没有改变太多,基本还是方法二那种。启发式函数改为切比雪夫距离距离。
距离计算方法有很多,常用启发式函数有这几种。选择合适的启发式函数有利于速度的提升。这题可以用好几种启发式函数,初学都可以试着都写一下。

曼哈顿距离(Manhattan Distance)
一般只能在四个方向上移动时用(右、左、上、下)

对角线距离(Diagonal Distance):
当我们只允许向八个方向移动时用(国际象棋中的王移动方式那种)

欧几里得距离(Euclidean Distance):
不受限制,允许向任何方向移动时。

切比雪夫距离(Chebyshev Distance):
可参考:[https://leetcode-cn.com/problems/minimum-time-visiting-all-points/solution/fang-wen-suo-you-dian-de-zui-xiao-shi-jian-by-le-2/](LeetCode 1266)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
public int shortestPathBinaryMatrix(int[][] grid) {
int n = grid[0].length;
int m = grid.length;

Queue<Integer> q = new LinkedList<>();
int count = 0;
q.add(0);
int size = q.size();

while(!q.isEmpty()){
for(int k = 0; k < size; k++){
int curr = q.poll();
int i = curr / n;
int j = curr % n;

if(grid[i][j] ==1) continue;
if(i == m-1 && j == n-1 && grid[i][j] == 0) return count+1;

if(grid[i][j] == 0){
grid[i][j] = 1;
if(i+1<n && j+1<n) q.add((i+1) * n + (j+1));
if(i+1<n && j-1>=0) q.add((i+1) * n + (j-1));
if(i+1<n) q.add((i+1) * n + j);
if(i-1>=0 && j-1>=0) q.add((i-1) * n + (j-1));
if(i-1>=0 && j+1<n) q.add((i-1) * n + (j+1));
if(j+1<n) q.add(i * n + (j+1));
if(j-1>=0) q.add(i * n + (j-1));
if(i-1>=0) q.add((i-1) * n + j);
}
}
size = q.size();
count++;
}
return -1;
}
}

117. Populating Next Pointers in Each Node II

Question

Given a binary tree

1
2
3
4
5
6
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

Populate each next pointer to point to its next right node. If > there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Solution

BFS搜索,从右至左将每层节点放入队列。
用一个size记录该层级放入节点的数量,每次循环将size-1,当size归零时放入新一层级的节点。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;

public Node() {}

public Node(int _val) {
val = _val;
}

public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/

class Solution {
public Node connect(Node root) {
if(root == null) return root;

Queue<Node> q = new LinkedList();
q.add(root);

while(!q.isEmpty()){
int size = q.size();
Node next = null;
while(size > 0){
size--;
Node curr = q.poll();
curr.next = next;
next = curr;
if(curr.right != null) q.add(curr.right);
if(curr.left != null) q.add(curr.left);
}
}
return root;
}
}

763. Partition Labels

You are given a string s. We want to partition the string into as many parts as possible so that each letter appears in at most one part.

Note that the partition is done so that after concatenating all the parts in order, the resultant string should be s.

Return a list of integers representing the size of these parts.

将英文字母出现的首尾作为intervals看待。
根据字符创建数组并填入左右的index。
根据左侧index排序数组。

从左至右,如果intervals有交集,则合并。
否则在答案中添加当前interval的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public List<Integer> partitionLabels(String s) {
int[][] alphabet = new int[26][2];
int head = s.charAt(0) - 'a';
for(int i = 0; i < s.length(); i++){
int index = s.charAt(i) - 'a';
if(head != index && alphabet[index][0] == 0) alphabet[index][0] = i;
alphabet[index][1] = i;
}

Arrays.sort(alphabet, (a,b) -> a[0] - b[0]);

List<Integer> ans = new ArrayList();
int[] hold = alphabet[0];
for(int i = 1; i < alphabet.length; i++){
if(alphabet[i][0] <= hold[1]){
hold[1] = Math.max(hold[1], alphabet[i][1]);
}
else{
ans.add(hold[1]-hold[0]+1);
hold = alphabet[i];
}
}
ans.add(hold[1]-hold[0]+1);
return ans;

}
}

547. Number of Provinces

There are n cities. Some of them are connected, while some are not. If city a is connected directly with city b, and city b is connected directly with city c, then city a is connected indirectly with city c.

A province is a group of directly or indirectly connected cities and no other cities outside of the group.

You are given an n x n matrix isConnected where isConnected[i][j] = 1 if the ith city and the jth city are directly connected, and isConnected[i][j] = 0 otherwise.

Return the total number of provinces.

DFS搜索,当map[i][i] = 1时加入搜索。
搜索时将map[i][i]设为0。遍历并递归其数列。
当map[i][i]等于0时,返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
int[][] map;
public int findCircleNum(int[][] isConnected) {
map = isConnected;
int count = 0;

for(int i = 0; i < isConnected.length; i++){
if(map[i][i] == 1){
count++;
dfs(i);
}
}
return count;
}

private void dfs(int i){
if(map[i][i] == 0){
return;
}
map[i][i] = 0;
for(int j = 0; j < map[0].length; j++){
if(map[i][j] == 1){
dfs(j);
}
}
}
}

713. Subarray Product Less Than K

Given an array of integers nums and an integer k, return the number of contiguous subarrays where the product of all the elements in the subarray is strictly less than k.

滑动窗口,维护一个窗口内的乘积。
当乘积小于目标值时,窗口右侧向右移动。每加入一个新数值,可以增加(j-i+1)个组合。
当乘积大于目标时,窗口左侧向右移动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
int i = 0;
int j = 0;
int product = nums[0];
int count = 0;

while(i < nums.length && j < nums.length){
if(product < k){
count += (j - i) + 1;
j++;
if(j < nums.length ) product *= nums[j];
}
else{
product /= nums[i];
i++;
}
}
return count;
}
}

209. Minimum Size Subarray Sum

Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray [numsl, numsl+1, …, numsr-1, numsr] of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead.

滑动窗口,先取最左侧数字。记录窗口的最小值。
如果小于目标值,则右侧窗口向右移动,扩大窗口。更新窗口内的值。
如果大于等于目标值,则左侧窗口向右移动,缩小窗口。更新窗口内的值。
同时如果窗口大小小于最小值则更新窗口最小值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int min = Integer.MAX_VALUE;
int left = 0;
int right = 0;
int sum = nums[0];
while(right < nums.length){
if(sum >= target){
min = Math.min(min, right - left + 1);
sum -= nums[left];
left++;
}
else{
right++;
if(right < nums.length) sum += nums[right];
}
}
return min == Integer.MAX_VALUE ? 0 : min;
}
}

计算前缀和。
前缀和[j]与前缀和的[i]的差就是i+1到j的和。
因此需要找到sum[j] - sum[i] >= k。
暴力枚举的话需要O(n^2^)的时间复杂度。

由于前缀和是有序的,因此我们可以采用二分搜索。
寻找sum[j] - k >= sum[i]。
Arrays.binarySearch方法可以返回查找到的目录。
如果没有该值,方法会返回一个负数,其取反(x取反相当于[-(x+1)])的值就是应该插入的目录。
将ans设置为无限大,如果(index - i)小于最小值则更新到ans。

时间复杂度O(nlogn)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int[] sum = new int[nums.length+1];
for(int i = 1; i <= nums.length; i++){
sum[i] = sum[i-1] + nums[i-1];
}

int ans = Integer.MAX_VALUE;
for(int i = 0; i < sum.length; i++){
int search = sum[i] + target;
int index = Arrays.binarySearch(sum, search);
if(index < 0){
index = ~index;
}
if(index < sum.length){
ans = Math.min(ans, index - i);
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}
200. Number of Islands

200. Number of Islands

Question

Given an m x n 2D binary grid grid which represents a map of ‘1’s (land) and ‘0’s (water), return the number of islands.

An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Solution

遍历所有点,如果等于1则对其进行DFS搜索。
在搜索的同时将1设为0。
如果等于0则递归返回。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
char[][] area;
public int numIslands(char[][] grid) {
area = grid;
int count = 0;

for(int i = 0; i < area.length; i++){
for(int j = 0; j < area[0].length; j++){
if(area[i][j] == '1'){
dfs(i, j);
count++;
}
}
}
return count;
}

private void dfs(int i, int j){
if(area[i][j] == '0'){
return;
}
area[i][j] = '0';

if( i+1 < area.length ){
dfs(i+1, j);
}
if( i-1 >= 0 ){
dfs(i-1, j);
}
if( j+1 < area[0].length ){
dfs(i, j+1);
}
if( j-1 >= 0 ){
dfs(i, j-1);
}
}
}

Solution 2

同样是dfs搜索遍历每个位置,然而这个方法使用visited[][]数组来记录点是否被访问过。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
int[][] visited;
char[][] map;
int[][] operations;
public int numIslands(char[][] grid) {
visited = new int[grid.length][grid[0].length];
map = grid;
int count = 0;
operations = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(visited[i][j] == 1 || map[i][j] == '0') continue;
dfs(i, j);
count++;
}
}
return count;
}

private void dfs(int x, int y){
if(x < 0 || x >= map.length || y < 0 || y >= map[0].length ) return;
if(visited[x][y] == 1 || map[x][y] == '0') return;
visited[x][y] = 1;
for(int[] operation : operations){
int m = x + operation[0];
int n = y + operation[1];
dfs(m, n);
}

}
}

560. Subarray Sum Equals K

Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.

对于数组中每个数字,计算其前缀的和。
前缀[i]减去前缀[j]的差,等于[j]-[i]之间数字的和。(类似一种DP,数组可以用一个变量代替。)

因此,原题目等于寻找找 前缀[i]-前缀[j] = k。
用哈希表储存已经遍历过的前缀和出现的次数。
每次遍历时先查看哈希表内是否有当前[前缀和-k]的键在。
如果有则加入到count中。
(哈希表中需要提前放入一个0键,值等于1,为了计算[前缀和-k]等于0的情况。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int subarraySum(int[] nums, int k) {

int[] sum = new int[nums.length + 1];
HashMap<Integer, Integer> map = new HashMap();
int count = 0;
map.put(0, 1);

for(int i = 1; i <= nums.length; i++){
sum[i] = sum[i-1] + nums[i-1];
count += map.getOrDefault(sum[i]-k, 0);
map.put(sum[i], map.getOrDefault(sum[i], 0) + 1);
}

return count;
}
}

238. Product of Array Except Self

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].

The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

You must write an algorithm that runs in O(n) time and without using the division operation.

当前数字之外的积等于左边所有数字的积乘以右边所有数字的积。
因此可以维护两个数组,分别计算从左到右的乘积,和从右到左的乘积。

由于返回答案不算占用空间,因此可以将左侧乘积的数组保存在答案数组上。
然后在遍历时,从右至左遍历,使用一个变量储存右边的乘积,直接将两者的乘积更新在答案数组上。
此时空间复杂度为O(1)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int[] productExceptSelf(int[] nums) {
int[] ans = new int[nums.length];
ans[0] = 1;

for(int i = 1; i < nums.length; i++){
ans[i] = ans[i-1] * nums[i-1];
}

int rightProduct = 1;

for(int j = nums.length-1; j >=0; j--){
ans[j] = ans[j] * rightProduct;
rightProduct *= nums[j];
}
return ans;
}
}

438. Find All Anagrams in a String

Given two strings s and p, return an array of all the start indices of p’s anagrams in s. You may return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

滑动窗口。采用两个数组分别计算两个字符串中字符出现的数量。

滑动窗口时,维护数组中字符串中字符出现的次数。
循环,判断两个字符串是否相等,如果相等,则将当前的左指针添加进答案。
移动窗口的左右指针,在数组中减少前一项出现的次数,增加后一项出现的次数。

通过维护一个表示两个字符串中字符差值的数组,可以将算法优化算法,而不必进行两个数组的比较。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> ans = new ArrayList();
if(p.length()>s.length()){
return ans;
}

int[] alphabet = new int[26];
int[] window = new int[26];

for(int i = 0; i < p.length(); i++){
alphabet[p.charAt(i) - 'a']++;
window[s.charAt(i) - 'a']++;
}

int i = 0;
int j = p.length();

while(j < s.length()){
if(Arrays.equals(alphabet, window)){
ans.add(i);
}
window[s.charAt(i) - 'a']--;
window[s.charAt(j) - 'a']++;
i++;
j++;
}

if(Arrays.equals(alphabet, window)){
ans.add(i);
}

return ans;

}
}

334. Increasing Triplet Subsequence

Given an integer array nums, return true if there exists a triple of indices (i, j, k) such that i < j < k and nums[i] < nums[j] < nums[k]. If no such indices exists, return false.

贪心算法。
将first与second初始化为最大值。
first保存遍历过的最小值。
second保存遍历过的大于之前最小值的最小值。

遍历数组。
条件一:如果数字小于现在第一个值,则更新第一个值。
(此时一定不满足条件二,因此可以安全地更新更小的数字。)
条件二:如果数字大于第一个值,且小于第二个值,则更新第二个值。
(此时第一个值已经被更新过了,满足第一个值小于第二个值。)
条件三:如果数字大于第二个值,则返回true。
(此时两个值一定都被更新过了,满足第一个值小于第二个值小于第三个值。)

注意:
更新first后,second不会更新,但是second的存在可以确保曾经存在first小于second。
如果此时数字大于second,则数组中存在Triplet Subsequence。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public boolean increasingTriplet(int[] nums) {
int first = Integer.MAX_VALUE;
int second = Integer.MAX_VALUE;

for(int num : nums){
if(num < first){
first = num;
}
else if(num > first && num < second){
second = num;
}
else if(num > second){
return true;
}
}
return false;
}
}

双向遍历,逐渐收紧搜索窗口。设置i,k两个指针分别在头尾。
当nums[j] <= nums[i],则更新i指针为j。
当nums[j] >= nums[k],则更新k指针为j。
如果找到符合条件的nums[i] < nums[j] < nums[k]则返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Solution {
public boolean increasingTriplet(int[] nums) {
boolean flag = true;
int i = 0;
int k = nums.length -1 ;
int j;
int count = 1;

while(i < k && i + count < k){
if(flag){
j = i + count;
if(nums[i] >= nums[j]){
i = j;
count = 1;
flag = true;
continue;
}
else if(nums[j] < nums[k]){
return true;
}
flag = !flag;
}
else{
j = k - count;
if(nums[k] <= nums[j]){
k = j;
count = 1;
flag = true;
continue;
}
else if(nums[j] > nums[i]){
return true;
}
else{
count++;
}
flag = !flag;
}
}
return false;
}
}

173. Binary Search Tree Iterator

Implement the BSTIterator class that represents an iterator over the in-order traversal of a binary search tree (BST):

BSTIterator(TreeNode root) Initializes an object of the BSTIterator class. The root of the BST is given as part of the constructor. The pointer should be initialized to a non-existent number smaller than any element in the BST.
boolean hasNext() Returns true if there exists a number in the traversal to the right of the pointer, otherwise returns false.
int next() Moves the pointer to the right, then returns the number at the pointer.
Notice that by initializing the pointer to a non-existent smallest number, the first call to next() will return the smallest element in the BST.

You may assume that next() calls will always be valid. That is, there will be at least a next number in the in-order traversal when next() is called.

此方法不用将所有节点一次性入栈,而是在获得next时更新栈内的节点,因此更省时间。
将根节点的所有左子节点入栈,此时栈顶为最小值。
next方法:返回当前的栈顶节点。如果栈顶节点存在右子节点,则将其所有的左子节点入栈。
hasNext方法:返回栈是否为空的非值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class BSTIterator {
Stack<TreeNode> stack;
public BSTIterator(TreeNode root) {
stack = new Stack();
updateStack(root);
}

public int next() {
TreeNode node = stack.pop();
updateStack(node.right);
return node.val;
}

public boolean hasNext() {
return !stack.isEmpty();
}

private void updateStack(TreeNode root){
while(root != null){
stack.push(root);
root = root.left;
}
}
}

/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/

DFS搜索,中序搜索,从右子节点至左子节点,先将所有元素入栈。
next方法:挤出栈顶并返回。
hasNext方法: 返回栈是否为空的非值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class BSTIterator {
Stack<TreeNode> stack;
public BSTIterator(TreeNode root) {
stack = new Stack();
initiateStack(root);
}

public int next() {
return stack.pop().val;
}

public boolean hasNext() {
return !stack.isEmpty();
}

private void initiateStack(TreeNode root){
if(root == null){
return;
}
initiateStack(root.right);
stack.push(root);
initiateStack(root.left);
}
}

/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/

986. Interval List Intersections

You are given two lists of closed intervals, firstList and secondList, where firstList[i] = [starti, endi] and secondList[j] = [startj, endj]. Each list of intervals is pairwise disjoint and in sorted order.

Return the intersection of these two interval lists.

A closed interval [a, b] (with a <= b) denotes the set of real numbers x with a <= x <= b.

The intersection of two closed intervals is a set of real numbers that are either empty or represented as a closed interval. For example, the intersection of [1, 3] and [2, 4] is [2, 3].

设置两个指针,分别指向两个intervals的头部。
循环,相交的left等于两者左端的较大值。right等于两者右端的较小值。
只有在left小于right时,两个interval才相交,填入列表。
然后更新两个interval中右端较小的指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {
List<int[]> ans = new ArrayList();
int i = 0;
int j = 0;

while(i < firstList.length && j < secondList.length){
int left = Math.max( firstList[i][0], secondList[j][0] );
int right = Math.min( firstList[i][1], secondList[j][1] );
if(left <= right){
ans.add(new int[]{left, right});
}
if(firstList[i][1] < secondList[j][1]) i++;
else j++;

}

int[][] ret = new int[ans.size()][2];
ans.toArray(ret);
return ret;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Solution {
public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {
int i = 0;
int j = 0;
ArrayList<int[]> ans = new ArrayList();
int[] holdA;
int[] holdB;

while(i < firstList.length && j < secondList.length){
holdA = firstList[i];
holdB = secondList[j];

int[] arr = new int[2];

if(holdA[0] <= holdB[0] && holdA[1] >= holdB[1]){
ans.add(holdB);
j++;
}
else if(holdA[0] >= holdB[0] && holdA[1] <= holdB[1]){
ans.add(holdA);
i++;
}
else if(holdA[0] <= holdB[0] && holdA[1] >= holdB[0]){
arr[0] = holdB[0];
arr[1] = holdA[1];
ans.add(arr);
i++;
}
else if(holdA[0] >= holdB[0] && holdB[1] >= holdA[0]){
arr[0] = holdA[0];
arr[1] = holdB[1];
ans.add(arr);
j++;
}
else if(holdA[1] <= holdB[1]){
i++;
}
else{
j++;
}
}
int[][] ret = new int[ans.size()][2];
ans.toArray(ret);
return ret;
}
}

844. Backspace String Compare

Given two strings s and t, return true if they are equal when both are typed into empty text editors. '#' means a backspace character.

Note that after backspacing an empty text, the text will continue empty.

辅助方法getNextValid,返回下一个有效值。
将两个指针分别设置在两个字符串的尾部。
当两指针有一个大于0时,进行循环。
每次都搜索两个指针的下一个有效值。
如果两个指针上的字符不同则返回false。

最后返回两个指针的停留位置是否相同。

注意:
如果有一个字符串指针先更新到0以下,另一个指针仍有可能更新到一个“#”字符位置。
此时最后的结应该是两个空字符串。
因此需要继续循环一次,得出其是否会归到零以下。如果此时归零则两者的指针位置仍然相等。

因此即使getNextValid返回的下一个值为负数也应该保留其数值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public boolean backspaceCompare(String s, String t) {
int i = s.length()-1;
int j = t.length()-1;

while(i >= 0 || j >= 0){
i = getNextValid(s, i);
j = getNextValid(t, j);
if( i >= 0 && j >= 0 && s.charAt(i) != t.charAt(j)){
return false;
}
i--;
j--;
}
return (i == j);
}

private int getNextValid(String s, int start){
int i = start;
int count = 0;
while(i >= 0 && (s.charAt(i) == '#' || count != 0)){
if(s.charAt(i) == '#'){
count++;
}
else{
count--;
}
i--;
}
return i;
}
}

435. Non-overlapping Intervals

Given an array of intervals intervals where intervals[i] = [starti, endi], return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.

首先对intervals按照后一项的大小进行排序。(直接将两数字相减作为比较值比Integer.compare方法更快。)
贪心算法,将已取得的最大值max设置为最小整数值。
遍历intervals,如果当前interval的左侧小于max,则不能选择该interval,计数加一。
反之则可以选择interval,更新max的值为interval的最大值。
返回总数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals, (a,b) -> a[1] - b[1]);
int max = Integer.MIN_VALUE;
int count = 0;
for(int[] interval : intervals){
if(interval[0] < max){
count++;
}
else{
max = interval[1];
}
}
return count;
}
}