746. Min Cost Climbing Stairs

746. Min Cost Climbing Stairs

Question

You are given an integer array cost where cost[i] is the cost of ith step on a staircase. Once you pay the cost, you can either climb one or two steps.

You can either start from the step with index 0, or the step with index 1.

Return the minimum cost to reach the top of the floor.

Solution

动态规划,每一个新位置的等于前一个位置加上其cost和前两个位置加上cost的较小值。

Code

1
2
3
4
5
6
7
8
9
class Solution {
public int minCostClimbingStairs(int[] cost) {
int[] dp = new int[cost.length+1];
for(int i = 2; i <= cost.length; i++){
dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
}
return dp[cost.length];
}
}
202. Happy Number

202. Happy Number

Question

Write an algorithm to determine if a number n is happy.

A happy number is a number defined by the following process:

  • Starting with any positive integer, replace the number by the sum of the squares of its digits.
  • Repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1.
  • Those numbers for which this process ends in 1 are happy.

Return true if n is a happy number, and false if not.

Solution

首先证明,快乐数的计算不会趋近于无穷大。
我们可以考虑每一个位数的最大数字(9999…999)。
其下一个数值等于(81*n)。
对于三位数以下,其最大的值得下一个结果不会大于243。
对于四位数以上,下一个结果会快速收缩到三位数。
因此计算结果不会趋近于无穷。

当我们计算快乐数的值时,形成了一个隐式链表。
因此我们可以用快慢指针的方式,查询链表上是否有环。
快指针比慢指针初始值快1个单位,且移动速度为慢指针的一倍。
如果链表中有环,则两者终能相遇。
如果fast指针先走到1,等于走到了链表的终点。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public boolean isHappy(int n) {
int slow = n, fast = getNext(n);
while(fast != 1 && fast != slow){
fast = getNext(getNext(fast));
slow = getNext(slow);
}
return fast == 1;
}

private int getNext(int n){
int sum = 0;
while(n != 0){
int digit = n % 10;
sum += (digit * digit);
n = n / 10;
}
return sum;
}
}
997. Find the Town Judge

997. Find the Town Judge

Question

In a town, there are n people labeled from 1 to n. There is a rumor that one of these people is secretly the town judge.

If the town judge exists, then:

  1. The town judge trusts nobody.
  2. Everybody (except for the town judge) trusts the town judge.
  3. There is exactly one person that satisfies properties 1 and 2.

You are given an array trust where trust[i] = [ai, bi] representing that the person labeled ai trusts the person labeled bi.

Return the label of the town judge if the town judge exists and can be identified, or return -1 otherwise.

Solution

题目可以转换为计算各个顶点的入度和出度。

遍历每条边,并计算边上两个顶点的出度和入度。
如果某个节点的入度为n-1,出度为0,则符合有法官的条件。
否则没有法官,返回-1。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int findJudge(int n, int[][] trust) {
int[] inDegrees = new int[n];
int[] outDegrees = new int[n];

for(int[] edge : trust){
outDegrees[edge[0]-1]++;
inDegrees[edge[1]-1]++;
}
for(int i = 0; i < n; i++){
if(outDegrees[i] == 0 && inDegrees[i] == n-1) return i+1;
}
return -1;
}
}

108. Convert Sorted Array to Binary Search Tree

Given an integer array nums where the elements are sorted in ascending order, convert it to a height-balanced binary search tree.

A height-balanced binary tree is a binary tree in which the depth of the two subtrees of every node never differs by more than one.

以中序遍历的顺序创建节点(代码实现时先序遍历),每次选择范围的中间值mid为根节点。
根节点的左子节点递归左侧left直到mid-1的位置。
根节点的右子节点递归mid+1直到右侧right的位置。
当left > right时,返回null作为二叉树的叶子节点。

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
/**
* 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 Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return build(nums, 0, nums.length-1);
}

private TreeNode build(int[] nums, int left, int right){
if(left > right) return null;

int mid = left + (right - left) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = build(nums, left, mid-1);
root.right = build(nums, mid+1, right);

return root;
}
}

155. Min Stack

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

Implement the MinStack class:

  • MinStack() initializes the stack object.
  • void push(int val) pushes the element val onto the stack.
  • void pop() removes the element on the top of the stack.
  • int top() gets the top element of the stack.
  • int getMin() retrieves the minimum element in the stack.

分别将数据保存在一个Priority Queue和一个栈中。
pop方法pop掉stack的内容,然后将其从优先队列中移除。
top方法返回stack的栈顶。
getMin方法返回优先队列的顶。

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 MinStack {
Queue<Integer> pq;
Stack<Integer> stack;
public MinStack() {
pq = new PriorityQueue<>();
stack = new Stack<>();
}

public void push(int val) {
pq.add(val);
stack.add(val);
}

public void pop() {
int i = stack.pop();
pq.remove(i);

}

public int top() {
return stack.peek();
}

public int getMin() {
return pq.peek();
}
}

/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/

290. Word Pattern

Given a pattern and a string s, find if s follows the same pattern.

Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in s.

先将s分割成数组。
如果words的长度和pattern的长度不同则返回false。
用长度为26的数组储存pattern的字符。
同时遍历words和pattern,将pattern的字符换算成数字作为index,将words[i]填入数组。
如果数组中已经有word存在,则检查新的word和数组内的word是否相等。
如果不相等,则返回false。

最后遍历数组,比对各个字符中对应的word是否相等,如果有相等的,则返回false。由于数组长度固定,因此这个操作的时间复杂度是O(1)。

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
class Solution {
public boolean wordPattern(String pattern, String s) {
String[] words = s.split(" ");
String[] alphabet = new String[26];

if(words.length != pattern.length()){
return false;
}

for(int i = 0; i < pattern.length(); i++){

if( alphabet[pattern.charAt(i) - 'a'] != null){
if(!alphabet[pattern.charAt(i) - 'a'].equals(words[i])){
return false;
}
}
else{
alphabet[pattern.charAt(i) - 'a'] = words[i];
}
}

for(int i = 0; i < alphabet.length; i++){
for(int j = i+1; j < alphabet.length; j++){
if(alphabet[i] == null || alphabet[j] == null){
continue;
}
if(alphabet[i].equals(alphabet[j])){
return false;
}
}
}

return true;
}
}

409. Longest Palindrome

Given a string s which consists of lowercase or uppercase letters, return the length of the longest palindrome that can be built with those letters.

Letters are case sensitive, for example, “Aa” is not considered a palindrome here.

回文字符串除了中心一个元素,其他的字符必须成对出现。因此可以直接统计字符串里有几组成对的字符。

用数组记录字符出现的次数。
如果数组中某个字符出现了两次,则可以将其归零。然后可以组成的最长回文数字加2。
如果字符串还剩下其他字符未选择,则最长回文数可以加一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int longestPalindrome(String s) {
int[] alphabet = new int['z' - 'A' + 1];
int count = 0;
int total = s.length();

for(int i = 0; i < s.length(); i++){
int index = s.charAt(i) - 'A';
alphabet[index]+=1;
if( alphabet[index] == 2 ){
total -= 2;
count += 2;
alphabet[index] = 0;
}
}

if(total != 0){
count++;
}

return count;
}
}

706. Design HashMap

Design a HashMap without using any built-in hash table libraries.

Implement the MyHashMap class:

MyHashMap() initializes the object with an empty map.
void put(int key, int value) inserts a (key, value) pair into the HashMap. If the key already exists in the map, update the corresponding value.
int get(int key) returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key.
void remove(key) removes the key and its corresponding value if the map contains the mapping for the key.

哈希表,先设置一个素数Prime作为map的尺寸。
(这里设置成素数是为了减少可能的碰撞。)
创建一个Pair类记录key和value。

map初始化时需要生成一个LinkedList数组。

  • hash方法计算哈希值。用key % Prime并返回。
  • put方法,根据key计算其哈希值h。如果列表中有则重新设置当前Pair的value。
  • get方法,根据哈希值h搜索并查找链表中的Pair,如果找到则返回Pair,否则返回-1。
  • remove方法,根据哈希值h搜索并remove链表中的Pair。
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class MyHashMap {
final int PRIME = 1009;
List<Pair>[] map;
public MyHashMap() {
map = new LinkedList[PRIME];
for(int i = 0; i < PRIME; i++){
map[i] = new LinkedList<Pair>();
}
}

public void put(int key, int value) {
int h = hash(key);
for(Pair p : map[h]){
if(p.getKey() == key){
p.setValue(value);
return;
}
}
Pair p = new Pair(key, value);
map[h].add(p);
}

public int get(int key) {
int h = hash(key);
for(Pair p : map[h]){
if(p.getKey() == key){
return p.value;
}
}
return -1;
}

public void remove(int key) {
int h = hash(key);
for(Pair p : map[h]){
if(p.getKey() == key){
map[h].remove(p);
return;
}
}
}

private int hash(int key){
return key % PRIME;
}
}

class Pair {
int key;
int value;
public Pair(int k, int v){
key = k;
value = v;
}

public int getKey(){
return key;
}
public int getValue(){
return value;
}
public void setValue(int v){
value = v;
}
}

/**
* Your MyHashMap object will be instantiated and called as such:
* MyHashMap obj = new MyHashMap();
* obj.put(key,value);
* int param_2 = obj.get(key);
* obj.remove(key);
*/

190. Reverse Bits

问题
Reverse bits of a given 32 bits unsigned integer.

Note:

  • Note that in some languages, such as Java, there is no unsigned integer type. In this case, both input and output will be given as a signed integer type. They should not affect your implementation, as the integer’s internal binary representation is the same, whether it is signed or unsigned.
  • In Java, the compiler represents the signed integers using 2’s complement notation. Therefore, in Example 2 above, the input represents the signed integer -3 and the output represents the signed integer -1073741825.

创建返回值ans。
每次向左移动一位ans,然后取n的尾数进行二进制或运算(相当于在尾部进行不进位的加和)。
然后将n向左移动一位。

  • 二进制下的或运算只保留两数间较大的位。(0011 | 0110 = 0111)
  • 二进制下的与运算只保留两数间皆为1的位。(0011 & 0110 = 0010)
  • 掩码(Mask)是在二进制下进行与运算。以1作为掩码时,前面的31为皆为0,因此进行与运算后只保留最后一位。

因此(n & 1)相当于n的二进制与000…001运算,只保留n的尾数。
然后(ans << 1)向左移动一位,用 | 操作将n的尾数加入ans。

1
2
3
4
5
6
7
8
9
10
11
public class Solution {
// you need treat n as an unsigned value
public int reverseBits(int n) {
int ans = 0;
for(int i = 0; i < 32; i++){
ans = (ans << 1) | (n & 1);
n >>= 1;
}
return ans;
}
}

136. Single Number

Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.

You must implement a solution with a linear runtime complexity and use only constant extra space.

位运算,对所有数值做二进制异或运算。
两个同样的值异或运算会等于0,最后和与单独的数字相等。

1
2
3
4
5
6
7
8
9
class Solution {
public int singleNumber(int[] nums) {
int ans = 0;
for(int num : nums){
ans = ans ^ num;
}
return ans;
}
}

排序,然后遍历数组,如果第i个值不等于第i+1个则返回。

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public int singleNumber(int[] nums) {
Arrays.sort(nums);
for(int i = 0; i < nums.length-1; i+=2){
if(nums[i] != nums[i+1]){
return nums[i];
}
}
return nums[nums.length-1];
}
}

70. Climbing Stairs

问题
You are climbing a staircase. It takes n steps to reach the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

递归,传入根节点,进行BFS搜索。
如果当前节点小于搜索的最低点,则抛弃该节点,继续搜索其右子节点。(由于是BST,右子节点大于节点本身)
如果当前节点大于搜索的最高点,则抛弃该节点,继续搜索其左子节点。
如果当前节点在搜索范围内,则保留该节点,继续递归该节点的两个子节点。
最后返回根节点。

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
/**
* 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 Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null){
return null;
}
if(root.val < low){
return trimBST(root.right, low, high);
}
if(root.val > high){
return trimBST(root.left, low, high);
}

root.left = trimBST(root.left, low, high);
root.right = trimBST(root.right, low, high);
return root;
}
}

191. Number of 1 Bits

问题
Write a function that takes an unsigned integer and returns the number of ‘1’ bits it has (also known as the Hamming weight).

Note:

  • Note that in some languages, such as Java, there is no unsigned integer type. In this case, the input will be given as a signed integer type. It should not affect your implementation, as the integer’s internal binary representation is the same, whether it is signed or unsigned.
  • In Java, the compiler represents the signed integers using 2’s complement notation. Therefore, in Example 3, the input represents the signed integer. -3.

位运算,[n-1]的二进制数字为[n]的二进制数字退一位。
二者的与运算结果相当于二进制下[n]减少最右侧的1。
例如01001000100011
两者的与运算结果为0100000。相当于减少了一位1。
计算循环次数就可以得出1的总数。

1
2
3
4
5
6
7
8
9
10
11
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int count = 0;
while(n != 0){
n = (n & (n-1));
count++;
}
return count;
}
}

231. Power of Two

问题
Given an integer n, return true if it is a power of two. Otherwise, return false.

An integer n is a power of two, if there exists an integer x such that n == 2x.

位运算,由于2^n^的二进制为[100…00],当2^n^-1时,其二进制为[11..11](少一位)。
两者进行按位与(&)运算,得到[000…00],与0相等。

1
2
3
4
5
6
7
8
class Solution {
public boolean isPowerOfTwo(int n) {
if (n <= 0){
return false;
}
return (n & (n - 1)) == 0;
}
}

递归,当(n <= 0)时,返回false。
当n等于1时,返回true。
当(n % 2)有余数时,返回false。
递归(n / 2)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public boolean isPowerOfTwo(int n) {
if (n <= 0){
return false;
}
if (n == 1){
return true;
}
if (n%2 != 0){
return false;
}
return isPowerOfTwo(n/2);
}
}

112. Path Sum

问题
Given the root of a binary tree and an integer targetSum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum.

A leaf is a node with no children.

递归,如果当前节点为null则返回false。
计算并更新当前节点的值。
如果当前节点为叶节点,且当前节点的值等于target,则返回true。
递归左子节点和右子节点,返回两者的或运算。

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
/**
* 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 Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
return hasPathSum(root,0,targetSum);
}

private boolean hasPathSum(TreeNode root, int parentVal, int target){
if (root == null){return false;}
root.val = root.val + parentVal;
if (root.left == null && root.right == null && root.val == target){
return true;
}
return ( hasPathSum(root.left, root.val, target) || hasPathSum(root.right, root.val, target));
}
}

104. Maximum Depth of Binary Tree

问题
Given the root of a binary tree, return its maximum depth.

A binary tree’s maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

递归,每次返回左子节点和右子节点中较大的结果+1。
当节点为null时返回0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 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 Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
}

BFS搜索,每次倾倒出队列里所有的元素并将level+1。
搜索完毕返回level。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}
Queue<TreeNode> q = new LinkedList();
q.offer(root);
int level = 0;
while(!q.isEmpty()){
int size = q.size();
for (int i = 0; i < size; i++){
TreeNode curr = q.poll();
if(curr.left!=null){q.offer(curr.left);}
if(curr.right!=null){q.offer(curr.right);}
}
level++;
}
return level;
}
}