6 、 旋转数组的最小数字
这种二分查找难就难在,arr[mid]跟谁比.
我们的目的是:当进行一次比较时,一定能够确定答案在mid的某一侧。一次比较为 arr[mid]跟谁比的问题。
一般的比较原则有:
- 如果有目标值target,那么直接让arr[mid] 和 target 比较即可。
- 如果没有目标值,一般可以考虑 端点
对于本题,非递减数组,选择右端点作为target比较好
- 时间复杂度:二分,所以为O(logN), 但是如果是[1, 1, 1, 1],会退化到O(n)
- 空间复杂度:没有开辟额外空间,为O(1)
low指针是最左端,high指针最右端,mid指针=low+(high-low)/2
执行前提是low<high,因为low=high则就是最终答案:{
如果low对应的数小于high对应的数,则low就是最小
如果mid大于high,一定在右端,因为此时low-mid全部大于high,所以low=mid+1,从右端搜索
否则就是mid小于high,一定在左端,所以high=mid
}
class Solution {
public int minArray(int[] numbers) {
int left=0,right=numbers.length-1;
while(left<right){
if(numbers[left]<numbers[right]) return numbers[left];
int mid=left+(right-left)/2;
if(numbers[mid]>numbers[right]){
left=mid+1;
}
else if(numbers[mid] == numbers[right]){
right = right - 1;
}
else{
right=mid;
}
}
return numbers[left];
}
}
class Solution {
public int minArray(int[] numbers) {
int i = 0, j = numbers.length - 1;
while (i < j) {
int m = (i + j) / 2;
if (numbers[m] > numbers[j]) i = m + 1;
else if (numbers[m] < numbers[j]) j = m;
else j--;
}
return numbers[i];
}
}
python
class Solution:
def minArray(self, numbers: [int]) -> int:
i, j = 0, len(numbers) - 1
while i < j:
m = (i + j) // 2
if numbers[m] > numbers[j]: i = m + 1
elif numbers[m] < numbers[j]: j = m
else: j -= 1
return numbers[i]
28 、 数组中出现次数超过一半的数字
sort 与 sorted 区别:
sort 只是应用在 list 上的方法,(就地排序无返回值)。
sorted 是内建函数,可对所有可迭代的对象进行排序操作,(返回新的list)
getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
getOrDefault() 方法的语法为:
hashmap.get(Object key, V defaultValue)
HASHMAP
import java.util.HashMap;
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array==null)
return 0;
HashMap<Integer,Integer> res=new HashMap<>();
int len = array.length;
for(int i=0;i<array.length;i++){
res.put(array[i],res.getOrDefault(array[i],0)+1);//意思就是当Map集合中有这个array[i]时,就使用这个array[i]对应的value值,如果没有这个array[i]就使用默认值0
if(res.get(array[i])>len/2)
return array[i];
}
return 0;
}
}
用preValue记录上一次访问的值,count表明当前值出现的次数,如果下一个值和当前值相同那么count++;如果不同count–,减到0的时候就要更换新的preValue值了,因为如果存在超过数组长度一半的值,那么最后preValue一定会是该值。
public class Solution {
public int MoreThanHalfNum_Solution(int [] array) {
if(array == null || array.length == 0)return 0;
int preValue = array[0];//用来记录上一次的记录
int count = 1;//preValue出现的次数(相减之后)
for(int i = 1; i < array.length; i++){
if(array[i] == preValue)
count++;
else{
count--;
if(count == 0){
preValue = array[i];
count = 1;
}
}
}
int num = 0;//需要判断是否真的是大于1半数,这一步骤是非常有必要的,因为我们的上一次遍历只是保证如果存在超过一半的数就是preValue,但不代表preValue一定会超过一半
for(int i=0; i < array.length; i++)
if(array[i] == preValue)
num++;
return (num > array.length/2)?preValue:0;
}
}
// 摩尔投票:超过一半的数 重复相加一定大于0
public int voteTest(int[] nums){
int vote_cnt = 0;
int ans = 0;
for(int num:nums){
if(vote_cnt == 0)
ans = num;
vote_cnt += ans == num?+1:-1;
}
return ans;
}
public int majorityElement(int[] nums) {
// return hashmapTest(nums);
// return rankTest(nums);
return voteTest(nums);
}
}
30、连续子数组的最大和
典型的动态规划。dp[n]代表以当前元素为截止点的连续子序列的最大和,如果dp[n-1]>0,dp[n]=dp[n]+dp[n-1],因为当前数字加上一个正数一定会变大;如果dp[n-1]<0,dp[n]不变,因为当前数字加上一个负数一定会变小。使用一个变量max记录最大的dp值返回即可
public int FindGreatestSumOfSubArray(int[] array) {
int max = array[0];
for (int i = 1; i < array.length; i++) {
array[i] += array[i - 1] > 0 ? array[i - 1] : 0;
max = Math.max(max, array[i]);
}
return max;
}
时间复杂度:O(n)
空间复杂度:O(n)
思想很简单,就是对下标为i的元素array[i],先试探的加上array[i], 如果和为负数,显然,以i结尾的元素对整个结果不作贡献。
具体过程:
初始化:维护一个变量tmp = 0
如果tmp+array[i] < 0, 说明以i结尾的不作贡献,重新赋值tmp = 0
否则更新tmp = tmp + array[i]
最后判断tmp是否等于0, 如果等于0, 说明数组都是负数,选取一个最大值为答案。
public class Solution {
public int FindGreatestSumOfSubArray(int[] array){
int ret = array[0];
int tmp = 0;
for(int k:array){
if(tmp+k<0){
tmp=0;
}
else{
tmp +=k;
}
ret =Math.max(ret,tmp);
}
if (tmp != 0){
return ret;
}
else {
Arrays.sort(array);
return array[array.length-1];
}
}
}
51、构建乘积数组
将题目拆成上三角和下三角,用递归的思想求解
参见
题解
public class Solution {
public int[] multiply(int[] A) {
if(A.length == 0) return new int[0];
int[] b = new int[A.length];
b[0] = 1;
int tmp = 1;
for(int i = 1; i < A.length; i++) {
b[i] = b[i - 1] * A[i - 1];
}
for(int i = A.length - 2; i >= 0; i--) {
tmp *= A[i + 1];
b[i] *= tmp;
}
return b;
}
}