面试算法题-01

1.在一个数组中找出有几个k,用O(log(n))算法实现
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int arr[10]={2,3,3,3,3,4,5};
int first(int k) {
    int left=0, right=7;
    while(left<=right) {
        int mid = (left+right)>>1;
        if(arr[mid]>k) right=mid-1;
        else if(arr[mid]<k) left=mid+1;
        else {
            if(arr[mid-1]==k && mid>0) {
                right = mid-1;
            }
            else return mid;
        }
    }
    return -1;
}
int last(int k) {
    int left=0, right=7;
    while(left<=right) {
        int mid = (left+right)>>1;
        if(arr[mid]>k) right=mid-1;
        else if(arr[mid]<k) left=mid+1;
        else {
            if(arr[mid-1]==k && mid<right-1) {
                left = mid+1;
            }
            else return mid;
        }
    }
    return -1;
}
int main() {
    int f = first(3);
    int l = last(3);
    if(f!=-1 && l!=-1) {
        printf("%d\n", l-f+1);
    }
    else printf("can not found\n");
    return 0;
}

2.判断平衡二叉树

struct BinaryTreeNode {
    int m_valuel;
    BinaryTreeNode *m_lson;
    BinaryTreeNode *m_rson;
};

//复杂度大于O(n),小于O(n^2)

int GetDepth(BinaryTreeNode *root) {
    if(root == NULL) {
        return 0;
    }
    int l = GetDepth(root->m_lson);
    int r = GetDepth(root->m_rson);
    return l>r?l+1:r+1;
}

bool IsBalanced(BinaryTreeNode *root) {
    if(root == NULL) return true;
    int l = GetDepth(root->m_lson);
    int r = GetDepth(root->m_rson);
    int dis = r-l;
    if(dis>=-1 && dis<=1) {
        return IsBalanced(root->m_lson)&&IsBalanced(root->m_rson);
    }
    else return false;

}
//后序遍历,复杂度O(n)
bool IsBalanced(BanaryTreeNode *root, int *depth) {
    if(root == NULL) {
        *depth=0;
        return true;
    }
    int l=0;
    int r=0;
    if(IsBalanced(root->m_lson,&l) && IsBalanced(root->m_rson,&r)) {
        int dis=l-r;
        if(dis>=-1 && dis<=1) {
            *depth=1+l>r?l:r;
            return true;
        }
        else return false;
    }else return false;
}

3.输入一个数组,其中有两个值是惟一的,其他都有两个,求这两个值,要求空间复杂度是O(1),时间复杂度O(n)
看了解答,觉得神他妈复杂,自己写了一个,试了几个例子,是对的

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
int arr[8] = {2,4,3,5,3,2,5,6};
int main() {
    sort(arr,arr+8);
    int flag=0;
    for(int i=0; i<7;) {
        if(arr[i]!=arr[i+1]) {
            printf("%d\n",arr[i]);
            i++;
            flag++;
        }
        else {
            i+=2;
        }
    }
    if(flag != 2) printf("%d\n",arr[7]);
}

这里补一下答案的代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
int arr[10]={2,4,4,6,3,2,5,5};
void FindNumAppearOnce(int n) {
    if(arr==NULL || n<2) return;
    int sum=0;
    for(int i=0; i<n; i++) {
        sum ^= arr[i];
    }
    int pos = 0;
    while((sum&1)!=1 && (pos<32)) {
        pos++;
        sum >>= 1;//右移
    }
    if(pos>=32) {
        return;
    }
    int one=0, two=0;
    int num=1<<pos;
    for(int i=0; i<n; i++) {
        if((arr[i]&num)!=0) {
            one ^= arr[i];
        }
        else {
            two ^= arr[i];
        }
    }
    printf("%d %d\n", one, two);

}

int main() {
    FindNumAppearOnce(8);
    return 0;

}

在一个数组里找两个数,这两个数的和是特定的值,要求时间为O(n),数组有序
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int arr[6] = {1,2,4,7,11,15};
int n = 6;
bool Find(int s, int& num1, int& num2) {
    bool isFind = false;
    if(arr==NULL || n<=0) {
        return isFind;
    }
    int p1=0, p2=n-1;
    while(p1<p2) {
        int sum=arr[p1]+arr[p2];
        if(sum == s) {
            isFind=true;
            num1=arr[p1],num2=arr[p2];
            break;
        }
        else if(sum > s) {
            p2--;
        }else p1++;
    }
    return isFind;
}
int main() {
    int a, b;
    if(Find(15,a,b)) printf("%d %d\n", a, b);
    else printf("not found\n");

    return 0;
}

给一个数n,从1-n中找出连续的串使得和为n,时间为O(n)
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
void print(int f, int t) {
    printf("%d", f);
    for(int i=f+1; i<=t; i++) printf(" %d", i);
    printf("\n");
}
void FindSequenceSum(int s) {
    if(s<3) return;
    int start=1,end=2,sum=3;
    int mid=(s+1)>>1;
    while(start<mid) {//超过一半接下来加的就是比一半大的数了,不可能得到s
        if(s == sum) {
            print(start,end);
            end++;
            sum += end;
        }else if(sum>s) {
            sum -= start;
            start++;
        }else {
            end++;
            sum += end;
        }

    }
}
int main() {
    FindSequenceSum(9);

    return 0;
}

题目:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。句子中单词以空格符隔开。为简单起见,标点符号和普通字母一样处理。例如输入“I am a student.”,则输出“student. a am I”。
代码:空间复杂度高

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
char str[105][100];
int main() {
    char s[105];
    memset(str, 0, sizeof(str));
    while(gets(s)) {
        int j = 0;
        for(int i=0; i<strlen(s);) {
            if(s[i]!=' ' && s[i] != '\n' && s[i] != '\0') {
                int z = 0;
                while(s[i]!=' ' && s[i] != '\n' && s[i] != '\0') {
                    str[j][z] = s[i];
                    z++, i++;
                }
                str[j][z] = '\0';
                j++;

            }else{
                i++;
            }
        }
        printf("%s", str[j-1]);
        for(int i=j-2; i>=0; i--) printf(" %s", str[i]);
        printf("\n");

    }

    return 0;
}

空间复杂度低:

#include <iostream>
#include<string>
#include<cstdio>
#include<cstring>

using namespace std;

void myReverse(char*, char*);
char * senReverse(char*);
int main()
{
    char sen[]="hello, I am a student!";
    char *result=senReverse(sen);
    cout << result << endl;
    return 0;
}
void myReverse(char *start, char* end) {
    char temp;
    while(start<end) {
        temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }

}

char * senReverse(char* sen) {
    char *start = sen, *end = sen+strlen(sen)-1;
    myReverse(start, end);
    end=start;
    while(*start != '\0') {
        if(*end==' '||*end=='\0') {
            myReverse(start,--end);
            if(*end=='\0') break;
            end+=2;
            start = end;

        }else ++end;
    }
    return sen;
}

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如输入字符串”abcdefg”和数字2,该函数将返回左旋转2位得到的结果”cdefgab”。
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
void ReverseWord(char* begin, char*end) {
    char temp;
    if(begin==NULL || end==NULL) {
        return;
    }
    while(begin<end) {
        temp = *begin;
        *begin = *end;
        *end = temp;
        begin++, end--;
    }
}
char* LeftRotateString(char* string, int k) {
    if(string==NULL || k<=0) return string;
    int len = (int)strlen(string);
    char* begin = string;
    char *end = string+len-1;
    if(k>len) return NULL;
    ReverseWord(begin, begin+k-1);
    ReverseWord(begin+k, end);
    ReverseWord(begin,end);
    return string;

}
int main() {
    char str[] = "abcdefg";
    char *string = NULL;
    string = LeftRotateString(str,2);
    cout<<string<<endl;
    return 0;
}

约瑟夫环路:
n个数从1-n形成一个环,每次删除环中的第m个数,求最后一个被删除的数
代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
struct ListNode {
    int value;
    ListNode *nextNode;
};
void BuildList(ListNode **headNode, int *arrNum, int n) {
    if(arrNum == NULL || n<=0) return;
    (*headNode)->value = arrNum[0];
    (*headNode)->nextNode=NULL;
    ListNode *pre = (*headNode);
    for(int i=1; i<n; i++) {
        ListNode *newNode = new ListNode();
        newNode->value = arrNum[i];
        newNode->nextNode = NULL;
        pre->nextNode = newNode;
        pre = newNode;
    }
    pre->nextNode = *headNode;
}
int GetLastNum(ListNode *headNode, int n, int m) {
    /*if(headNode==NULL || n<=0 || m<=0) {
        throw exception("error");
    }*/
    int count=n;
    ListNode *pNode = headNode;
    while(count>1) {
        int pos = 1;
        while(pos<m-1) {
            ++pos;
            pNode=pNode->nextNode;
        }
        ListNode *tmpNode = pNode->nextNode;
        pNode->nextNode = tmpNode->nextNode;
        delete tmpNode;
        tmpNode = NULL;
        --count;
        pNode=pNode->nextNode;
    }
    return pNode->value;
}
void print(ListNode* headNode) {
    ListNode *pNode = headNode;
    cout<<pNode->value<<endl;
    pNode=pNode->nextNode;
    while(pNode!=headNode) {
        cout<<pNode->value<<endl;
        pNode=pNode->nextNode;
    }
}
int main() {
    int arrNum[] = {1,2,3,4,5};
    ListNode *headNode = new ListNode();
    BuildList(&headNode,arrNum,5);
//  print(headNode);
    int ans = GetLastNum(headNode, 5, 3);
    printf("%d\n", ans);
    return 0;
}

用位运算求两数相加:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int GetSum(int num1, int num2) {
    while(num2 != 0) {
        int sum = num1^num2;
        int carry = (num1&num2)<<1;
        num1=sum;
        num2=carry;
    }
    return num1;
}
int GetSum2(int num1, int num2) {
    if(num2==0) return num1;
    int sum = num1^num2;
    num2 = (num2&num1)<<1;
    num1 = sum;
    GetSum(num1, num2);
}

int main() {
    int ans = GetSum2(5,6);
    printf("%d\n", ans);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值