2.14
给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。
请你找出并返回只出现一次的那个数。
你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。
时间复杂度比较难实现,我可以随便写出两种On的
1.哈希表
class Solution {
public int singleNonDuplicate(int[] nums) {
HashMap<Integer,Integer>map=new HashMap<>();
for(int num:nums){
if(map.containsKey(num)){
map.remove(num);
}else{
map.put(num, 1);
}
}
int ans=0;
for(int num:map.keySet()){
ans=num;
}
return ans;
}
}
2.异或
class Solution {
public int singleNonDuplicate(int[] nums) {
int ans = 0;
for(int x : nums){
ans = ans^x;
}
return ans;
}
}
O(logn)很显然需要二分 ,毕竟二分查找的时间复杂度摆在这,那我们怎么做呢?
注意到一个点,目标数字的下标一定为偶数,如果偶数和他右边的数字相同,证明还没找到目标数字,如果奇数和他左边的数字相同,证明已经过了目标数字,根据这个来二分。
class Solution {
public int singleNonDuplicate(int[] nums) {
int n = nums.length;
int l = 0, r = n - 1;
//r为结果位置
while (l < r) {
int mid = l + r >> 1;
//注意偶数考虑右边,奇数考虑左边
if (mid % 2 == 0) {
//如果还没到目标数,取右半部分
if (mid + 1 < n && nums[mid] == nums[mid + 1]) l = mid + 1;
else r = mid;
//奇数位
} else {
//已经过了目标数,取左半部分
if (mid - 1 >= 0 && nums[mid - 1] == nums[mid]) l = mid + 1;
else r = mid;
}
}
return nums[r];
}
}
2.15
给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。
幸运数是指矩阵中满足同时下列两个条件的元素:
在同一行的所有元素中最小
在同一列的所有元素中最大
显然这个幸运数只有一个或者零个,我们可以用两轮遍历,第一轮统计每行最小的数和每列最大的数,用row和col两个数组统计,第二轮遍历,如果matrix[i][j]==row[i]&&matrix[i][j]==col[j],证明该数字符合幸运数特征
class Solution {
public List<Integer> luckyNumbers (int[][] matrix) {
int m=matrix.length,n=matrix[0].length;
List<Integer>ans=new ArrayList<>();
int[]row=new int[m],col=new int[n];
Arrays.fill(row, Integer.MAX_VALUE);
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
row[i]=Math.min(row[i],matrix[i][j]);
col[j]=Math.max(col[j],matrix[i][j]);
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(matrix[i][j]==row[i]&&matrix[i][j]==col[j]){
ans.add(matrix[i][j]);
}
}
}
return ans;
}
}