牛客学堂第四节

定义局部最小的概念。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中任
意一个局部最小出现的位置即可。

int sovel(vector<int>a,int n){


    if(n<1||a.size()==0)
        return -1;
    if(n==1)
        return 0;
    int l=0,r=n-1;
    if(a[l]<a[l+1])
        return l;
    if(a[r]<a[r-1])
        return r;




    l++,r--;
    int mid=(l+r)/2;
    while(l!=r){
        int mid=(l+r)/2;
        if(a[mid]>a[mid-1]){
            r=mid-1;
        }
        else if(a[mid]>a[mid+1]){
            l=mid+1;
        }
        else{
            return mid;
        }
    }
    return l;
}

2.给定一个double类型的数组arr,其中的元素可正可负可0,返回子数组累乘的最大乘积。
例如arr=[-2.5,4,0,3,0.5,8,-1],子数组[3,0.5,8]累乘可以获得最大的乘积12,
所以返回12。

int sovel(double a[],int n){
    if(a==NULL||n<=0)
        return -1;
    double mx=a[0],mn=a[0],res=a[0];
    for(int i=1;i<n;i++){
        double nNewm=mx*a[i];
        double nNewn=mn*a[i];
        mx=max(max(nNewm,nNewn),a[i]);
        mn=min(min(nNewm,nNewn),a[i]);
        res=max(mx,res);
    }
    return res;
}

3.给定一棵完全二叉树的头节点head,返回这棵树的节点个数。如果完全二叉树的节点数为N,
请实现时间复杂度低于O(N)的解法。

typedef struct Node{
    int data;
    Node* lch;
    Node* rch;
}Node;


int creatTree(Node **pNode){
    int x;
    cin>>x;
    if(x<0){
        *pNode=NULL;
        return 0;
    }
    *pNode=new Node();
    (*pNode)->data=x;
    creatTree(&((*pNode)->lch));
    creatTree(&((*pNode)->rch));
    return 1;
}


void dfs(Node *head){
    if(head==NULL)
        return;
    cout<<head->data<<" ##";
    dfs(head->lch);
    dfs(head->rch);


}
void dfs2(Node *head){
    if(head==NULL)
        return;


    dfs2(head->lch);
    dfs2(head->rch);cout<<head->data<<" !!";


}
void dfs1(Node *head){
    if(head==NULL)
        return;


    dfs1(head->lch);
    cout<<head->data<<" ";
    dfs1(head->rch);
}


int NodeNum(Node * head,int hight){


    if(head==NULL)
        return 0;
    if(hight==1)
        return 1;
    cout<<"@@"<<endl;
    Node *pNode=head->rch;
    int h=1;
    while(pNode!=NULL){
        pNode=pNode->lch;
        h++;
    }
    cout<<"!!"<<h<<endl;
    if(h==hight){
        cout<<"h==hight "<<pow(2,h-1)<<endl;
        return pow(2,h-1)+NodeNum(head->rch,hight-1);
    }
    else{
        cout<<"h!=hight "<<pow(2,h)<<endl;
        return pow(2,h-1)+NodeNum(head->lch,hight-1);
    }
}


int main(){
    Node *Head=new Node();
    while(creatTree(&Head)){
        Node *pNode=Head;
        int h=1;


        while(pNode->lch!=NULL){
            pNode=pNode->lch;
            h++;
        }
        int num=NodeNum(Head,h);
        cout<<"num="<<num<<endl;


    }






}

4.给定两个有序数组arr1和arr2,两个数组长度都为N,求两个数组中所有数的上中位数。
例如:
arr1 = {1,2,3,4};
arr2 = {3,4,5,6};
一共8个数则上中位数是第4个数,所以返回3。
arr1 = {0,1,2};
arr2 = {3,4,5};
一共6个数则上中位数是第3个数,所以返回2。
要求:时间复杂度O(logN)

int upmid(int a[],int b[],int l1,int r1,int l2,int r2){// n======0->n-1
   // int num;
    int n=(r1-l1+1);cout<<" n="<<n<<endl;
    if(n==1)
        return a[l1] < b[l2] ? a[l1] : b[l2];
    if(n%2==0){//o
        int mda=(r1+l1)/2;
        int mdb=(r2+l2)/2;//cout<<"md=("<<mda<<" "<<mdb<<")"<<a[mda]<<" "<<b[mdb]<<endl;
        if(a[mda]==b[mdb])
            return a[mda];
        else if(a[mda]>b[mdb]){
            return upmid(a,b,l1,mda,mdb+1,r2);
        }
        else{//a[md]<b[md]
            return upmid(a,b,mda+1,r1,l2,mdb);
        }
    }
    else{//j
        int mda=(r1+l1)/2;
        int mdb=(r2+l2)/2;
        if(a[mda]==b[mdb])
            return a[mda];
        else if(a[mda]>b[mdb]){
            return upmid(a,b,l1,mda,mdb,r2);
        }
        else{//a[md]<b[md]
            return upmid(a,b,mda,r1,l2,mdb);
        }
    }


}


void findNum(int a[],int b[],int n){
        if(n==0||a==NULL||b==NULL)//len1!=len2
            cout<<"input you wenti"<<endl ;
        else{
            int num=upmid(a,b,0,n-1,0,n-1);
            cout<<"upmidNum="<<num<<endl;
        }
}

5.给定两个有序数组arr1和arr2,在给定一个整数k,返回两个数组的所有数中第K小的数。
例如:
arr1 = {1,2,3,4,5};
arr2 = {3,4,5};
K = 1;
因为1为所有数中最小的,所以返回1;
arr1 = {1,2,3};
arr2 = {3,4,5,6};
K = 4;
因为3为所有数中第4小的数,所以返回3;

要求:如果arr1的长度为N,arr2的长度为M,时间复杂度请达到O(log(min{M,N}))。

int upmid(int a[],int b[],int l1,int r1,int l2,int r2){// n======0->n-1
   // int num;
    int n=(r1-l1+1);//cout<<" n="<<n<<endl;
    if(n==1)
        return a[l1] < b[l2] ? a[l1] : b[l2];
    if(n%2==0){//o
        int mda=(r1+l1)/2;
        int mdb=(r2+l2)/2;//cout<<"md=("<<mda<<" "<<mdb<<")"<<a[mda]<<" "<<b[mdb]<<endl;
        if(a[mda]==b[mdb])
            return a[mda];
        else if(a[mda]>b[mdb]){
            return upmid(a,b,l1,mda,mdb+1,r2);
        }
        else{//a[md]<b[md]
            return upmid(a,b,mda+1,r1,l2,mdb);
        }
    }
    else{//j
        int mda=(r1+l1)/2;
        int mdb=(r2+l2)/2;
        if(a[mda]==b[mdb])
            return a[mda];
        else if(a[mda]>b[mdb]){
            return upmid(a,b,l1,mda,mdb,r2);
        }
        else{//a[md]<b[md]
            return upmid(a,b,mda,r1,l2,mdb);
        }
    }


}


int findNum(int a[],int b[],int n,int m,int k){
    //a < b传进来时保证大小
    if(a==NULL||b==NULL||n<=0||m<=0||k<=0||k>m+n)
        return -1;


    if(k<=n){
        return upmid(a,b,0,k-1,0,k-1);
    }
    else if(k>n&&k<=m){
        int lNo=k-n-1;
        int rNo=k;
        if(a[lNo]>b[n-1])
            return a[lNo];
        else
            return upmid(a,b,0,n-1,lNo,rNo);
    }
    else{//k>m && k<=m+n
        int x=k-n-1;
        int y=m-1;
        int l=k-m-1;
        int r=n-1;
        if(a[l]>=b[m-1])
            return a[l];
        else if(b[x]>=a[n-1])
            return b[x];
        else
            return upmid(a,b,l+1,r,x+1,y);
    }
}

//-----------------------------------------------------------------------------华丽分割线---------------------------------------------------------------------------------------------老师的标准答案

//1--------------------------------------
public int getLessIndex(int[] arr) {
if (arr == null || arr.length == 0) {
return -1; // no exist
}
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;
}

//2------------------------------------------------
public double maxProduct(double[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
double max = arr[0];
double min = arr[0];
double res = arr[0];
double maxEnd = 0;
double minEnd = 0;
for (int i = 1; i < arr.length; ++i) {
maxEnd = max * arr[i];
minEnd = min * arr[i];
max = Math.max(Math.max(maxEnd, minEnd), arr[i]);
min = Math.min(Math.min(maxEnd, minEnd), arr[i]);
res = Math.max(res, max);
}
return res;
}

//3---------------------------------------------------------
public int nodeNum(Node head) {
if (head == null) {
return 0;
}
return bs(head, 1, mostLeftLevel(head, 1));
}
public int bs(Node node, int l, int h) {
if (l == h) {
return 1;
}
if (mostLeftLevel(node.right, l + 1) == h) {
return (1 << (h - l)) + bs(node.right, l + 1, h);
} else {
return (1 << (h - l - 1)) + bs(node.left, l + 1, h);
}
}
public int mostLeftLevel(Node node, int level) {
while (node != null) {
level++;
node = node.left;
}
return level - 1;
}

//4-----------------------------------------------------
public static int getUpMedian(int[] arr1, int[] arr2) {
if (arr1 == null || arr2 == null || arr1.length != arr2.length) {
throw new RuntimeException("Your arr is invalid!");
}
return findProcess(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1);
}
public static int findProcess(int[] arr1, int start1, int end1, int[] arr2,
int start2, int end2) {
if (start1 == end1) {
return Math.min(arr1[start1], arr2[start2]);
}
// 元素个数为奇数,则offset为0;元素个数为偶数,则offset为1;
int offset = ((end1 - start1 + 1) & 1) ^ 1;
int mid1 = (start1 + end1) / 2;
int mid2 = (start2 + end2) / 2;
if (arr1[mid1] > arr2[mid2]) {
return findProcess(arr1, start1, mid1, arr2, mid2 + offset, end2);
} else if (arr1[mid1] < arr2[mid2]) {
return findProcess(arr1, mid1 + offset, end1, arr2, start2, mid2);
} else {
return arr1[mid1];
}
}


//5-------------------------------------------------
public static int findKthNum(int[] arr1, int[] arr2, int kth) {
if (arr1 == null || arr2 == null) {
throw new RuntimeException("Your arr is invalid!");
}
if (kth < 1 || kth > arr1.length + arr2.length) {
throw new RuntimeException("K is invalid!");
}
int[] longArr = arr1.length >= arr2.length ? arr1 : arr2;
int[] shortArr = arr1.length < arr2.length ? arr1 : arr2;
int lenL = longArr.length;
int lenS = shortArr.length;
if (kth <= lenS) {
return getUpMedian(shortArr, 0, kth - 1, longArr, 0, kth - 1);
}
if (kth > lenL) {
if (shortArr[kth - lenL - 1] >= longArr[lenL - 1]) {
return shortArr[kth - lenL - 1];
}
if (longArr[kth - lenS - 1] >= shortArr[lenS - 1]) {
return longArr[kth - lenS - 1];
}
return getUpMedian(shortArr, kth - lenL, lenS - 1, longArr, kth - lenS, lenL - 1);
}
if (longArr[kth - lenS - 1] >= shortArr[lenS - 1]) {
return longArr[kth - lenS - 1];
}
return getUpMedian(shortArr, 0, lenS - 1, longArr, kth - lenS, kth - 1);
}
public static int getUpMedian(int[] arr1, int start1, int end1, int[] arr2,
int start2, int end2) {
if (start1 == end1) {
return Math.min(arr1[start1], arr2[start2]);
}
int offset = ((end1 - start1 + 1) & 1) ^ 1;
int mid1 = (start1 + end1) / 2;
int mid2 = (start2 + end2) / 2;
if (arr1[mid1] > arr2[mid2]) {
return getUpMedian(arr1, start1, mid1, arr2, mid2 + offset, end2);
} else if (arr1[mid1] < arr2[mid2]) {
return getUpMedian(arr1, mid1 + offset, end1, arr2, start2, mid2);
} else {
return arr1[mid1];
}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值