二分搜索
1局部最小值位置
定义局部最小的概念。arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]是局部最小;如果arr[N-1]<arr[N-2],那么arr[N-1]是局部最小;如果0<i<N-1,既有arr[i]<arr[i-1]又有arr[i]<arr[i+1],那么arr[i]是局部最小。 给定无序数组arr,已知arr中任意两个相邻的数都不相等,写一个函数,只需返回arr中任意一个局部最小出现的位置即可。
public class Solution { public int getLessIndex(int[] arr){ if(arr.length==0) return -1; if(arr.length==1) return 0; if(arr[0]<arr[1]) return 0; if(arr[arr.length-1]<arr[arr.length-2]) return arr.length-1; for(int i=1;i<arr.length-2;i++){ if(arr[i]<arr[i-1]&&arr[i]<arr[i+1]){ return i; } } return -1; } }
采用二分搜索做法,时间复杂度为O(lgn)
1.arr长度为0,返回-1,表示局部最小位置不存在
2.如果长度为1,返回0,此时0是局部最小位置
3.如果arr长度大于1,先判断arr[0]、arr[1]大小,arr[n-2]、arr[n-1]大小
public class Solution { public int getLessIndex(int[] arr) { if(arr==null||arr.length==0){ return -1; } if(arr.length ==1||arr[0]<arr[1]){ return 0; } if(arr[arr.length-1]<arr[arr.length-2]){ return arr.length-1; } int left = 1; int right = arr.length-2; int mid = 0; while(left<right){ mid = (left+right)/2; if(arr[mid]>arr[mid-1]){ right = mid-1; } else if(arr[mid]>arr[mid+1]){ left = mid+1; } else{ return mid; } } return left; } }
另一种二分法
public class Solution { public int getLessIndex(int[] arr){ int n=arr.length; if(arr==null||n==0) return -1; if(n==1) return 0; if(arr[0]<arr[1]) return 0; if(arr[n-1]<arr[n-2]) return n-1; return getMid(arr,1,n-2); } public int getMid(int[] arr,int left,int right){ // int left=0; // int right=arr.length-1; int mid=(left+right)/2; while(left<right){ if(arr[mid]>arr[mid-1]){ right = mid-1; return getMid(arr,left,right); } else if(arr[mid]>arr[mid+1]){ left = mid+1; return getMid(arr,left,right); } else{ return mid; } } return -1; } }
2元素最左出现
对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置。
给定一个数组arr及它的大小n,同时给定num。请返回所求位置。若该元素在数组中未出现,请返回-1。
[1,2,3,3,4],5,3
返回:2
自己写的代码
import java.util.*; public class LeftMostAppearance { public int findPos(int[] arr, int n, int num) { // write code here int res=-1; int left=0; int right=n-1; int mid=0; while(left<=right){ mid=(left+right)/2; if(num<=arr[mid]){ right=mid-1; }else if(num>arr[mid]){ left=mid+1; } res=left; } return res; } }
牛客网上代码
import java.util.*; public class LeftMostAppearance { public int findPos(int[] arr, int n, int num) { // write code here if(arr==null || n==0) return -1; int res=-1; int left=0; int right=n-1; int mid; while(left<=right){ mid=left+(right-left)/2; if(arr[mid]<num){ left=mid+1; }else if(arr[mid]>num){ right=mid-1; }else{ right=mid-1; res=mid; } } return res; } }
3循环有序数组最小值
对于一个有序循环数组arr,返回arr中的最小值。有序循环数组是指,有序数组左边任意长度的部分放到右边去,右边的部分拿到左边来。比如数组[1,2,3,3,4],是有序循环数组,[4,1,2,3,3]也是。
给定数组arr及它的大小n,请返回最小值。
[4,1,2,3,3],5
返回:1
思路:arr[L]<arr[R] 有序,min=arr[L]
arr[L]>=arr[R] arr[L]>arr[M] L-M
arr[M]>arr[R] M-R
arr[L]<=arr[M]&&arr[M]<=arr[R] =>arr[L]=arr[M]=arr[R] 遍历数组
自己写的代码
import java.util.*; public class MinValue { public int getMin(int[] arr, int n) { // write code here int left=0; int right=n-1; int min=arr[0]; if(arr[left]<arr[right]){ min=arr[left]; }else{ while(left<=right){ int mid=(left+right)/2; if(arr[left]>arr[mid]){ min=arr[mid]; right=mid-1; }else if(arr[mid]>arr[right]){ min=arr[mid]; left=mid+1; }else{ for(int i=1;i<n;i++){ if(arr[i]<min){ min=arr[i]; } } break; } } } return min; } }
牛客网上代码
1left、mid、right
arr[left]>arr[mid] right=mid
arr[mid]>arr[left] left=mid
else mid++;
break;
import java.util.*; public class MinValue { public int getMin(int[] arr, int n) { if(n==0||arr== null) return -1; int left = 0; int right = n-1; int mid = (left+right)/2; if(arr[left]<arr[right]){ return arr[left]; } while(left < right){ mid = (left+right)/2; if(arr[left]>arr[mid]) right =mid; else if(arr[mid]>arr[left]) left = mid; else { mid++; break; } } return arr[mid]; } }
2
import java.util.*; public class MinValue { public int getMin(int[] arr, int n) { if (arr == null || arr.length == 0) { return -1; } int left = 0; int right = n - 1; int mid = 0; while (left<right){ //当数组只有两个值的时候 if (left==right-1){ break; } //左边小于右边,left到right范围内是有序的 if (arr[left]<arr[right]){ return arr[left]; } mid=(left+right)/2; if (arr[left]>arr[mid]){ //证明最小值在Left和mid之间 right=mid; continue; } if (arr[mid]>arr[right]){//证明最小值在mid和right之间 left=mid; continue; } //当出现等值的情况 while (left<right){ if (arr[left]==arr[mid]){ left++; }else if (arr[left]<arr[mid]){ return arr[left]; }
//else{
//					right=mid;
//					break;
//				}
} } } return Math.min(arr[left],arr[right]); } }
4最左原位
有一个有序数组arr,其中不含有重复元素,请找到满足arr[i]==i条件的最左的位置。如果所有位置上的数都不满足条件,返回-1。
给定有序数组arr及它的大小n,请返回所求值。
[-1,0,2,3],4
返回:2
自己写的代码1
import java.util.*; public class Find { public int findPos(int[] arr, int n) { // write code here for(int i=0;i<n;i++){ if(arr[i]==i) return i; } return -1; } }
自己写的代码2
import java.util.*; public class Find { public int findPos(int[] arr, int n) { // write code here if(arr[0]>n||arr[n-1]<0) return -1; int res=-1; int left=0; int right=n-1; int mid=0; while(left<=right){ mid=(left+right)/2; if(arr[mid]>mid){ right=mid-1; }else if(arr[mid]<mid){ left=mid+1; }else{ res=mid; right=mid-1; } } return res; } }
牛客网上的代码
import java.util.*; public class Find { public int findPos(int[] arr, int n) { if (arr == null || n == 0) { return -1; } if (arr[0] > (n - 1)) { // 数组本身有序,第一个数都比最后一个大,肯定不存在 return -1; } if (arr[n - 1] < 0) {// 最后一个数都小于0,则前面的数更不可能出现 arr[i] == i的情况 return -1; } int left = 0; int right = n - 1; int mid = 0; int res = -1; while (left <= right) { mid = (left + right) / 2; if (arr[mid] > mid) { // 下标是按1进行递增,中间的值比中间的下标都大,则右边不会存在arr[i]==i的情况 right = mid - 1; } if (arr[mid] < mid) { // 左边不存在arr[i]==i 的情况 left = mid + 1; } if (arr[mid] == mid) { res = mid; // 但仍需要在左边进行寻找 right = mid - 1; } } return res; } }
5完全二叉树计数
给定一棵完全二叉树的根节点root,返回这棵树的节点个数。如果完全二叉树的节点数为N,请实现时间复杂度低于O(N)的解法。
给定树的根结点root,请返回树的大小。
牛客网上的代码1
import java.util.*; /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } }*/ public class CountNodes { public int count(TreeNode root) { //1.先找到完全二叉树左子树最左边节点的层数。然后再找出右子树的左节点能到达的层数 //2.看左右子树的左节点能到的层数相等,则左子树必定是一个满二叉树,那使用满二叉树的性质求出左子树的节点数,右子树的节点数使用递归方式求出 //3.如果左右子树的左节点能到的层数不相等,则右子树必定是一颗少一层的满二叉树。然后左子树使用递归方法求出节点数 return bsCount(root,1,mostLeftlevel(root,1)); } public int bsCount(TreeNode node,int start,int height){//start表示从头节点开始位置,height表示左子树左节点能到达的层数 if(start == height){ return 1;//只有一个头结点 } if(mostLeftlevel(node.right,start+1) == height){//说明左子树是一颗满二叉树:start+1是因为右子树没包含跟节点 return (1<<(height - start))+bsCount(node.right,start+1,height); }else{//说明右子树是比层数少一的满二叉树 return (1<<(height - start - 1))+bsCount(node.left,start+1,height); } } public int mostLeftlevel(TreeNode node,int level){ while(node != null){ level++;//包括了头结点 node = node.left; } return level-1; } }
牛客网上的代码2
import java.util.*; /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } }*/ public class CountNodes { public int count(TreeNode root) { if (root == null) { return 0; } int count = 1;// 默认加上头结点 // 获得层数 TreeNode temp = root.left; // int zuoCenShu = temp == null ? 0 : 1; int zuoCenShu = 0; while (temp != null) { temp = temp.left; zuoCenShu++; } // 检测右子树 temp = root.right; int youCenShu = 0; while (temp != null) { temp = temp.left; youCenShu++; } // 判断层数是否相等 if (youCenShu == zuoCenShu && zuoCenShu != 0) { // 说明左子树为满二叉树 count = (int) Math.pow(2, zuoCenShu) + count(root.right); } else { // 说明右子树为满 count = (int) Math.pow(2, youCenShu) + count(root.left); } return count; } }
6快速N次方
如果更快的求一个整数k的n次方。如果两个整数相乘并得到结果的时间复杂度为O(1),得到整数k的N次方的过程请实现时间复杂度为O(logN)的方法。
给定k和n,请返回k的n次方,为了防止溢出,请返回结果Mod 1000000007的值。
2,3
返回:8
import java.util.*; public class QuickPower { public int getPower(int k, int N) { // write code here if(N == 0){ return 1; } if(N == 1){ return k; } if(N % 2 == 0) { long tmp = getPower(k, N / 2); tmp = (tmp * tmp) % 1000000007; return (int)tmp; }else { long tmp = getPower(k, (N - 1) / 2); tmp = (tmp * tmp) % 1000000007; return (int)((tmp * k) % 1000000007); } } }
import java.util.*; public class QuickPower { public int getPower(int k, int N) { // write code here if(k==0){ return 0; } if(k==1){ return 1; } if(N==0){ return 1; } long modNum=1000000007; long res=1; long tmp=k; for(;N>0;N>>=1){ if((N&1)!=0){ res*=tmp; } tmp=(tmp*tmp)%modNum; res=res%modNum; } return (int)res; } }
import java.util.*; public class QuickPower { public int getPower(int k, int N) { long con = 1000000007; // write code here int factor = N; long res = 1; long tmp = k; while(factor>0){ if((factor&1)!=0){ res=(res*tmp)%con; } tmp = (tmp*tmp)%con; factor=factor>>1; } return (int)res; } }
                    
                
                
            
        
浙公网安备 33010602011771号