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);
*/

56. Merge Intervals

Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.

先对数组进行排序。
遍历数组,当前一个子数组与后一个子数组有重叠时,合并数组。

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[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a,b) -> Integer.compare(a[0],b[0]));

int i = 0;
List<int[]> ans = new ArrayList();
while( i < intervals.length-1 ){
if(intervals[i][1] >= intervals[i+1][0]){
intervals[i+1][0] = intervals[i][0];
intervals[i+1][1] = Math.max(intervals[i][1], intervals[i+1][1]);
intervals[i] = null;
}
i++;
}

for(int[] interval : intervals){
if(interval != null){
ans.add(interval);
}
}
return ans.toArray(new int[ans.size()][2]);
}
}

82. Remove Duplicates from Sorted List II

Given the head of a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. Return the linked list sorted as well.

使用队列暂存遍历的节点。
初始化prev为一个dummy节点。
如果当前节点不等于队列里节点的值,则倾倒出队列里的值。如果队列此时只有一个值,则将其添加到prev.next。
遍历完毕后如果队列内只有一个值则将其设置到prev.next。
最后返回dummy.next。

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
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
Queue<ListNode> q = new LinkedList();
ListNode dummy = new ListNode(0);
ListNode prev = dummy;
ListNode curr = head;
while(curr != null){
if(q.isEmpty() || curr.val == q.peek().val){
q.offer(curr);
curr = curr.next;
}
else{
if(q.size()==1){
prev.next = q.poll();
prev = prev.next;
prev.next = null;
}
else{
q.clear();
}
}
}

if(q.size()==1){
prev.next = q.poll();
}

return dummy.next;
}

}

162. Find Peak Element

A peak element is an element that is strictly greater than its neighbors.

Given an integer array nums, find a peak element, and return its index. If the array contains multiple peaks, return the index to any of the peaks.

You may imagine that nums[-1] = nums[n] = -∞.

You must write an algorithm that runs in O(log n) time.

二分搜索,由于只需要搜索任意一个山峰,因此只要向上走,一定可以走到一个峰。
当中值的下一个值是增长时(向上爬山),则更新左侧指针的位置为中值+1。继续搜索下一个中值。
否则更新右侧指针的位置为当前中值,等于向左侧进行搜索。
最后返回左侧指针停留的位置。
时间复杂度为O(logn)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int findPeakElement(int[] num) {
int left = 0;
int right = num.length - 1;

while (left < right) {
int mid1 = (right - left) / 2 + left;
int mid2 = mid1 + 1;
if (num[mid1] < num[mid2])
left = mid1+1;
else
right = mid1;
}
return left;
}
}

一次遍历,找到峰值,返回其index。
时间复杂度为O(n)。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int findPeakElement(int[] nums) {
int peak = 0;

for(int i = 0; i < nums.length; i++){
if(nums[i] > nums[peak]){
peak = i;
}
}
return peak;
}
}

分治法,每次将数组分为两组,向下递归。
当数组长度为1时返回元素,比较返回来的两个数值的大小。
返回其中的峰值index。
此解法时间为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 findPeakElement(int[] nums) {
return findPeak(nums,0,nums.length-1);
}

private int findPeak(int[] nums, int left, int right){
if(left == right){
return left;
}
int mid = left + (right - left) / 2;
int i = findPeak(nums, left, mid);
int j = findPeak(nums, mid+1, right);

if(nums[i] > nums[j]){
return i;
}
else{
return j;
}
}
}
48. Rotate Image

48. Rotate Image

Question

You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise).

You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.

Solution 1

此方法是in-place算法。

visited[][]数组记录访问情况,遍历所有位置,如果已访问则跳过。
循环替换矩阵上的每一个位置,如果已经访问过则break。
如果未访问则将要替换位置的值保存,并且在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
class Solution {
public void rotate(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] visited = new int[m][n];

for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(visited[i][j] == 1) continue;
int x = i, y = j;
int value = matrix[i][j];
while(true){
int s = n-1-x, t = y;
if(visited[t][s] == 1) break;
int temp = matrix[t][s];
matrix[t][s] = value;
value = temp;
visited[t][s] = 1;
x = t;
y = s;
}
}
}
}
}

Solution 2

此方法类似Solution 1,但是并非原地算法。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public void rotate(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] mat = new int[m][n];

for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
int s = n-1-i, t = j;
mat[t][s] = matrix[i][j];
}
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
matrix[i][j] = mat[i][j];
}
}
}
}

Solution 3

辅助方法getPixel计算旋转后的像素位置。
旋转时候矩阵内的四个分区的像素会互相替换。
因此需要将需要旋转的初始位置记录进入队列。
旋转图像时根据getPixel方法计算出需要替换的位置。
然后依次替换像素。

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
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
Queue<Integer> queue = new LinkedList();
for (int p = 0; p < n/2; p++){
for(int q = 0; q < (n+1)/2; q++){
queue.offer(p * n + q);
}
}

while(!queue.isEmpty()){
int i = queue.poll();
int INDEX = i;
boolean flag = true;
int temp = matrix[i/n][i%n];
while(i != INDEX || flag ){
flag = false;
int j = getPixel(n, i);
int swap = matrix[j / n][j % n];
matrix[j / n][j % n] = temp;
temp = swap;
i = j;
}
}
}

private int getPixel(int n, int o){
int row = o / n;
int col = o % n;
int newRow = col;
int newCol = n - (row + 1);
return (newRow * n) + newCol;
}
}