// https://leetcode.com/problems/majority-element-ii/description/
public class Solution {
public List<Integer> majorityElement(int[] nums) {
//there should be at most 2 different elements in nums more than n/3
//so we can find at most 2 elements based on Boyer-Moore Majority Vote algo
List<Integer> res = new ArrayList<Integer>();
if(nums.length==0) return res;
int count1=0,count2=0,m1=0,m2=0;
for(int n : nums){
if(m1==n) count1++;
else if(m2==n) count2++;
else if(count1==0) {
m1=n;
count1=1;
}
else if(count2==0) {
m2=n;
count2=1;
}
else{
count1--;
count2--;
}
}
count1=0;
count2=0;
//count the number for the 2 elements
for(int n:nums){
if(n==m1) count1++;
else if(n==m2) count2++;
}
//if those appear more than n/3
if(count1>nums.length/3) res.add(m1);
if(count2>nums.length/3) res.add(m2);
return res;
}
}
class Solution {
int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int slidingPuzzle(int[][] board) {
// edge cases
// find 0 position
int r0 = 0, c0 = 0, row = board.length, col = board[0].length;
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
if (board[r][c] == 0) {r0 = r; c0 = c; break;}
}
}
State begin = new State(board, 0, r0, c0); // initial state
PriorityQueue<State> pq = new PriorityQueue<>();
Set<State> inQueue = new HashSet<>();
pq.offer(begin);
inQueue.add(begin);
// BFS
while (!pq.isEmpty()) {
State curr = pq.poll();
if (curr.reachTarget()) return curr.step;
for (int[] d : dirs) {
int r = curr.r0 + d[0];
int c = curr.c0 + d[1];
State next = curr.move(r, c);
if (next == null || inQueue.contains(next)) continue;
pq.offer(next);
inQueue.add(next);
}
}
return -1;
}
}
class State implements Comparable<State> {
int[][] board;
int step, r0, c0, row, col;
public State(int[][] matrix, int k, int i, int j) {
row = matrix.length; col = matrix[0].length;
this.board = new int[row][col]; // deep copy passed matrix
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
board[r][c] = matrix[r][c];
}
}
this.step = k;
this.r0 = i;
this.c0 = j;
}
public State move(int i, int j) {
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length) return null; // out of boundary
State res = new State(this.board, step + 1, i, j);
int tmp = res.board[i][j];
res.board[i][j] = res.board[r0][c0];
res.board[r0][c0] = tmp;
return res;
}
public boolean reachTarget() {
return distanceToTarget() == 0;
}
public int distanceToTarget() {
int sum = 0;
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
int val = board[r][c];
if (val == 0) continue;
int i = (val - 1) / 3; // this value suppossed to in this cell
int j = (val - 1) % 3;
sum += Math.abs(r - i) + Math.abs(c - j);
}
}
return sum;
}
@Override
public boolean equals(Object obj) {
State that = (State) obj;
return Arrays.deepEquals(this.board, that.board);
}
@Override
public int hashCode() {
return Arrays.deepHashCode(this.board);
}
@Override
public int compareTo(State that) {
return (distanceToTarget() + step) - (that.distanceToTarget() + that.step);
}
}
Binary Indexed Tree
BIT explain: https://www.topcoder.com/thrive/articles/Binary%20Indexed%20Trees Key: one index is responsible for storing value representing a previous range, which is (index - getLSB(index), index]. E.g. index 12(1100) is responsible for (8, 12], i.e. (1000, 1100].
void update(int idx, int val) {
while (idx <= MaxIdx) {
tree[idx] += val;
idx += (idx & -idx);
}
}
int read(int idx) {
int sum = 0;
while (idx > 0) {
sum += tree[idx];
idx -= (idx & -idx);
}
return sum;
}
// "(idx & -idx)" is to get least significant non-zero bit, can also do idx & ~(idx-1), which is more intuitive.