import java.util.*;
/**
* NC377 有序数组中出现一次的元素
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param v int整型一维数组
* @return int整型
*/
public int singleElement (ArrayList<Integer> v) {
// return solution1(v);
return solution11(v);
// return solution2(v);
// return solution3(v);
// return solution4(v);
// return solution5(v);
}
/**
* 二分
* @param v
* @return
*/
private int solution1(ArrayList<Integer> v){
int n = v.size();
int result = -1;
int left = 0;
int right = n-1;
int mid;
int pre,after;
while(left <= right){
mid = left+(right-left)/2;
if(mid%2 == 1){
pre = mid-1;
after = mid+1;
if(0<=pre && v.get(pre).equals(v.get(mid))){
left = mid+1;
continue;
}
if(after<n && v.get(mid).equals(v.get(after))){
right = mid-1;
continue;
}
}
// 最终结果一定是在 偶数索引位置
else{
pre = mid-1;
after = mid+1;
// if(0<=pre && v.get(pre).equals(v.get(mid))){
// right = mid-1;
// continue;
// }
// if(after<n && v.get(mid).equals(v.get(after))){
// left = mid+1;
// continue;
// }
// 可减2
if(0<=pre && v.get(pre).equals(v.get(mid))){
right = mid-2;
continue;
}
// 可加2
if(after<n && v.get(mid).equals(v.get(after))){
left = mid+2;
continue;
}
// 前后 都不相同
result = v.get(mid);
break;
}
}
return result;
}
/**
* 二分
* @param v
* @return
*/
private int solution11(ArrayList<Integer> v){
int n = v.size();
int result = -1;
int left = 0;
int right = n-1;
int mid;
int pre,after;
while(left <= right){
mid = left+(right-left)/2;
if(mid%2 == 1){
pre = mid-1;
after = mid+1;
if(0<=pre && v.get(pre).equals(v.get(mid))){
left = mid+1;
}else if(after<n && v.get(mid).equals(v.get(after))){
right = mid-1;
}
}else{
pre = mid-1;
after = mid+1;
if(0<=pre && v.get(pre).equals(v.get(mid))){
right = mid-2;
}else if(after<n && v.get(mid).equals(v.get(after))){
left = mid+2;
}else{
result = v.get(mid);
break;
}
}
}
return result;
}
/**
* 二分: 简化
* @param v
* @return
*/
private int solution2(ArrayList<Integer> v){
int n = v.size();
int left = 0;
int right = n-1;
int mid;
int pre,after;
while(left < right){
mid = left+(right-left)/2;
if(mid%2 == 1){
pre = mid-1;
if(0<=pre && v.get(pre).equals(v.get(mid))){
left = mid+1;
}else{
right = mid;
}
}else{
after = mid+1;
if(after<n && v.get(mid).equals(v.get(after))){
// left = mid+1;
// 可加2
left = mid+2;
}else{
right = mid;
}
}
}
return v.get(left);
}
/**
* 二分: 再简化
* @param v
* @return
*/
private int solution3(ArrayList<Integer> v){
int n = v.size();
int left = 0;
int right = n-1;
int mid;
while(left < right){
mid = left+(right-left)/2;
if(v.get(mid).equals(v.get(mid^1))){
left = mid+1;
}else{
right = mid;
}
}
return v.get(left);
}
/**
* 二进制: 位运算(异或^)
* @param v
* @return
*/
private int solution4(ArrayList<Integer> v){
int result = 0;
for(int num: v){
result ^= num;
}
return result;
}
/**
* 遍历
* @param v
* @return
*/
private int solution5(ArrayList<Integer> v){
int n = v.size();
int result = 0;
for(int i=0; i<n; i+=2){
if((i==n-1) || (!v.get(i).equals(v.get(i+1)))){
result = v.get(i);
break;
}
}
return result;
}
}