面试算法题-01

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

#include
#include
#include
#include
#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]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]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
#include
#include
#include
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
#include
#include
#include
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; iint pos = 0;
    while((sum&1)!=1 && (pos<32)) {
        pos++;
        sum >>= 1;//右移
    }
    if(pos>=32) {
        return;
    }
    int one=0, two=0;
    int num=1<for(int i=0; iif((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
#include
#include
#include
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(p1int 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
#include
#include
#include
#include
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//超过一半接下来加的就是比一半大的数了,不可能得到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
#include
#include
#include
#include
#include
#include
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 
#include
#include
#include

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(startchar * 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
#include
#include
#include<string>
#include
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<0;
}

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

#include
#include
#include
#include
#include
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*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<value<nextNode;
    while(pNode!=headNode) {
        cout<value<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
#include
#include
#include
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;
}

你可能感兴趣的:(面试算法题)