源地址
https://app.codility.com/programmers/lessons/8-leader/equi_leader/
EquiLeader
给定一个含有N个整数的非空数组A.
一个 equi leader 指的是下标S ,数组A被S ( 0 ≤ S < N − 1) 分割为两个数组,这两个数组拥有相同的Leader.
比如:
A[0] = 4
A[1] = 3
A[2] = 4
A[3] = 4
A[4] = 4
A[5] = 2
有两个 equi leader
- 0, 因为 (4) 和 (3, 4, 4, 4, 2) 有相同的 leader 4.
- 2, 因为 (4, 3, 4) 和 (4, 4, 2) 有相同的 leader 4.
写一个函数,给定一个数组包含N个整数的非空数组A,返回 equi leader的个数.
class Solution {
public int solution(int[] A);
}
比如
A[0] = 4
A[1] = 3
A[2] = 4
A[3] = 4
A[4] = 4
A[5] = 2
函数返回2.
假定:
- N是范围在 [1…100,000]的整数
- A中的每个元素都是范围在 [−1,000,000,000…1,000,000,000]的整数
第一步
如果把一个数组分为两个子数组,两个字数组的Leader相等,那么这子Leader一定和原数组的Leader相等.
那么可以先求出数组A的Leader,然后依次判断各个子数组是否含有相同值的Leader.
public int solution(int[] A) {
int count = 0;
Integer leader = getLeader(A);
if (leader == null) {
return count;
}
int N = A.length;
for (int i = 0; i < N - 1; i++) {
int countLeft = 0;
for (int j = 0; j <= i; j++) {
if (A[j] == leader.intValue()) {
countLeft++;
}
}
if (countLeft <= (i + 1) / 2)
continue;
int countRight = 0;
for (int j = i + 1; j < N; j++) {
if (A[j] == leader.intValue()) {
countRight++;
}
}
if (countRight > (N - i - 1) / 2)
count++;
}
return count;
}
Integer getLeader(int[] A) {
int N = A.length;
LinkedList<Integer> stack = new LinkedList<Integer>();
for (int i = 0; i < N; i++) {
if (stack.size() == 0) {
stack.add(A[i]);
} else {
if (stack.getLast() != A[i]) {
stack.removeLast();
} else {
stack.addLast(A[i]);
}
}
}
if (stack.size() == 0)
return null;
int candidate = stack.getLast();
int count = 0;
for (int i = 0; i < N; i++) {
if (A[i] == candidate) {
count++;
}
}
return count > N / 2 ? candidate : null;
}
优化一下
上面的solution中有重复计算的部分.在计算子数组中candidate的个数的时候,不用每一次都从0到N-1计算一边,只有第一次需要遍历全部,后面每次移动index的时候判断当前元素是否等于candidate,然后加上或者建议1 即可.
public int solution(int[] A) {
int count = 0;
Integer leader = getLeader(A);
if (leader == null) {
return count;
}
int N = A.length;
int countLeft = 0;
int countRight = 0;
// calculate the count of leader where index = 0
if (A[0] == leader.intValue())
countLeft++;
for (int i = 1; i < N; i++) {
if (A[i] == leader.intValue())
countRight++;
}
if (countLeft > 0 && countRight > (N - 1) / 2) {
count++;
}
// move the index from 0 to N-1 and calculate the count of leader
for (int i = 1; i < N - 1; i++) {
if (A[i] == leader.intValue()) {
countLeft++;
countRight--;
}
if (countLeft > (i + 1) / 2 && countRight > (N - i - 1) / 2) {
count++;
}
}
return count;
}
Integer getLeader(int[] A) {
int N = A.length;
LinkedList<Integer> stack = new LinkedList<Integer>();
for (int i = 0; i < N; i++) {
if (stack.size() == 0) {
stack.add(A[i]);
} else {
if (stack.getLast() != A[i]) {
stack.removeLast();
} else {
stack.addLast(A[i]);
}
}
}
if (stack.size() == 0)
return null;
int candidate = stack.getLast();
int count = 0;
for (int i = 0; i < N; i++) {
if (A[i] == candidate) {
count++;
}
}
return count > N / 2 ? candidate : null;
}