电子科技大学 820 算法题


修改于2022.1.1
写在前面:
转载请注明本文链接:https://www.cnblogs.com/jxingh/p/15598210.html

820算法题

数组

1、数组逆置问题(左移、右移)

void reverse(int a[],int left, int right){
    int temp;
    for(int i=left,j=right; i<j; ++i,--j){
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
}



2、数组中超过一半的数字

// 默认都是正整数,存在则返回c,不存在则返回-1
int majorityElement(vector<int>& nums) {
    int n = nums.size();
    int c = nums[0];
    int num = 1;
    for(int i=1; i<n; i++){
        if(num == 0) c = nums[i];
        if(nums[i] == c) ++num;
        else --num;
    }
    num = 0;
    for(int i=0; i<n; i++){
        if(nums[i] == c) num++;
    }
    if(num > n/2) return c;
    else return -1;
}

3、荷兰国旗问题

void sortColor(int nums[], int length){
    int i=0, j=0, k=length-1;
    while(j<=k){
        if(nums[j]<0){
            Swap(nums+i, nums+j);
            i++;
            j++;
        }
        else if(nums[j]==0){
            j++;
        }
        else{
            Swap(nums+j, nums+k);
            k--;
        }
    }
}

4、股票最佳卖出时机

int maxProfit(vector<int>& prices) {
    if(prices.size() < 2) return 0;
    int res = 0, min = prices[0];
    for(int i = 1; i < prices.size(); i++) {
        if(prices[i] <= min) {
            min = prices[i];
        }else {
            res = res > (prices[i] - min) ? res : (prices[i] - min);
        }
    }
    return res;
}

int getMax(int* array, int n) {
    int res = INT_MIN, max = array[0];
    for(int i = 1; i < n; i++) {
        if(array[i] >= max) {
            max = array[i];
        }else {
            res = res > (max - array[i]) ? res : (max - array[i]);
        }
    }
    return res;
}

链表

struct ListNode{
    int val;
    ListNode *next;
};

1、反转链表

ListNode* reverseList(ListNode* head) {
    ListNode* p = head;
    head = NULL;
    while(p){
        ListNode* q = p;
        p = p->next;
        q->next = head;
        head = q;
    }
    return head;
}
// 头结点不含信息

2、合并两升序链表

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    ListNode *head = (ListNode*) malloc(sizeof(ListNode));
    ListNode* p = head;
    while(l1 && l2){
        if(l1->val < l2->val){
            p->next = l1;
            l1 = l1->next;
        }
        else {
            p->next = l2;
            l2 = l2->next;
        }
        p = p->next;
    }
    if(l1 == NULL) p->next =l2;
    else p->next = l1;
    return head->next;
}

3、反向打印链表

vector<int> reversePrint(ListNode* head) {
    if(!head) return {};
    vector<int> vec;
    stack<int> st;
    while(head){
        st.push(head->val);
        head = head->next;
    }
    while(!st.empty()){
        vec.push_back(st.top());
        st.pop();
    }
    return vec;
}
// printf(head->next);

4、寻找相交链表的公共结点

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    if(!headA || !headB) return NULL;
    ListNode* p=headA;
    ListNode* q=headB;
    int lenA=0;
    int lenB=0;
    while(p){
        lenA++;
        p=p->next;
    }
    while(q){
        lenB++;
        q=q->next;
    }
    p=headA;
    q=headB;
    if(lenA>lenB){
        int len=lenA-lenB;
        while(len){
            p=p->next;
            len--;
        }
    }
    else{
        int len=lenB-lenA;
        while(len){
            q=q->next;
            len--;
        }
    }
    while(p){
        if(p==q) return p;
        p=p->next;
        q=q->next;
    }
    return NULL;
}

5、倒数第k个结点

ListNode* getKthFromEnd(ListNode* head, int k) {
    if(head==NULL || k<1) return NULL;
    ListNode* fast=head;
    ListNode* slow=head;
    while(k > 0){
        if(fast == NULL) return NULL;
        fast = fast->next;
        k--;
    }
    while(fast!=NULL){
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}

6、判断链表是否有环

bool hasCycle(ListNode *head) {
    if(head == NULL || head->next == NULL) return false;
    ListNode* fast=head;
    ListNode* slow=head;
    while(fast != NULL && fast->next != NULL){
        slow=slow->next;
        fast=fast->next->next;
        if(fast == slow) return true;
    }
    return false;
}

7、寻找链表中点(有两个中间结点,则返回第二/一个中间结点)

ListNode* middleNode(ListNode* head) {
    if(head == NULL || head->next == NULL) return head;
    ListNode *slow = head;
    ListNode *fast = head;
    while(fast && fast->next){
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

8、删除链表的倒数第 N 个结点(思考)

ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode *fast = head;
    ListNode *slow = head;
    for(int i=0; i<n; i++) {
        fast = fast->next;
    }
    ListNode *p = NULL;
    if(fast==NULL){
        p = head;
        head = p->next;
        delete p;
        return head;
    }
    while(fast->next) {
        fast = fast->next;
        slow = slow->next;
    }
    p = slow->next;
    slow->next = p->next;
    delete p;
    return head;
}

栈和队列(简答题)

1、双队列实现栈(2018)


2、双栈实现队列


3、循环链表实现队列(2021)

// q入队
ListNode *p = rear->next;
rear->next = q;
q->next = p;
rear = q;
// 出队
rear->next = rear->next->next;

二叉树

struct TreeNode{
    int val;
    TreeNode *left, *right;
};

1、前中后序遍历

void preOrder(TreeNode* root){
    if(root!=NULL){
        visit(root);
        preOrder(root->left);
        preOrder(root->right);
    }
}

void inOrder(TreeNode* root){
    if(root!=NULL){
        inOrder(root->left);
        visit(root);
        inOrder(root->right);
    }
}

void postOrder(TreeNode* root){
    if(root!=NULL){ 
        postOrder(root->left);
        postOrder(root->right);
        visit(root);
    }
}

2、层次遍历

//按层输出
vector<vector<int>> levelOrder(TreeNode* root) {
    //if(root == NULL) return {};
    vector<vector<int>> res;
    queue<TreeNode*> Q;
    if(root) Q.push(root);
    while(!Q.empty()){
        int len = Q.size();  //记录当前层的节点数
        vector<int> vec;
        for(int i=0; i<len; ++i){
            TreeNode *p = Q.front();
            q.pop();
            vec.push_back(p->val);
            if(p->left != NULL) Q.push(p->left);
            if(p->right != NULL) Q.push(p->right);
        }
        res.push_back(vec);
    }
    return res;
}

3、二叉树高度

int height(TreeNode* root){
    if (root == NULL) return 0;
    int L = height(root->left); 
    int R = height(root->right); 
    return (L > R ? L : R) + 1;
}

4、判断对称二叉树(镜像)(2021)

// 一个树的左子树与右子树镜像对称,那么这个树是对称的
//两个树互为镜像:
//  它们的两个根结点具有相同的值
//  每个树的右子树都与另一个树的左子树镜像对称
bool isSymmetric(TreeNode* root) {
    if(root==NULL) return true;
    return check(root->left, root->right);
}
bool check(TreeNode *p, TreeNode *q) {
    //递归的终止条件是两个节点都为空
    //或者两个节点中有一个为空
    //或者两个节点的值不相等
    if (p==NULL && q==NULL) return true;
    else if (p==NULL || q==NULL) return false;
    return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
}

5、判断平衡二叉树

bool isBalanced(TreeNode* root) {
    if (root == NULL) return true;
    else {
        return abs(height(root->left) - height(root->right)) <= 1 && 
            isBalanced(root->left) && isBalanced(root->right);
    }
}
int height(TreeNode* root){
    if (root == NULL) return 0;
    int L = height(root->left); 
    int R = height(root->right); 
    return (L > R ? L : R) + 1;
}
// 时间复杂度:O(n^2),空间复杂度:O(n)
// 思考:时间复杂度怎么降到 O(n)?
bool isBalanced(TreeNode* root) {
    return height(root)>=0;
}
int height(TreeNode* root) {
    if(root == NULL) return 0;
    int L = height(root->left);
    int R = height(root->right);
    if(L == -1 || R == -1 ||  abs(L - R) > 1)
        return -1;
    /** 左子树已经返回-1了就不需要再递归右子树
    * int L, R;
    * if((L = height(root->left)) == -1 || (R = height(root->right)) == -1 ||  abs(L - R) > 1)
    * return -1;
    */
    return (L > R ? L : R) + 1;
}

6、判断完全二叉树(王道141)

bool isCompleteTree(TreeNode* root) {
    if(root == NULL) return true;
    queue<TreeNode*> Q;
    Q.push(root);
    while(!Q.empty()) {
        TreeNode *p = Q.front();
        Q.pop();
        if(p!=NULL) {
            Q.push(p->left);
            Q.push(p->right);
        }
        else {
            while(!Q.empty()) {
                TreeNode *p = Q.front();
                Q.pop();
                if(p!=NULL) return false;
            }
        }
    }
    return true;
}

7、判断二叉搜索树

vector<int> res;
bool isValidBST(TreeNode* root) {
    if(!root) return true;
    inOrder(root);
    for(int i=1; i<res.size(); ++i){
        if(res[i] <= res[i-1]) return false;
    }
    return true;
}
void inOrder(TreeNode* root) {
    if(root) {
        inOrder(root->left);
        res.push_back(root->val);
        inOrder(root->right);
    }
}
bool isValidBST(TreeNode* root) {
    return preOrder(root, INT_MIN, INT_MAX);
}
bool preOrder(TreeNode* root, int low, int high){
    if(root==NULL) return true;
    if(root->val <= low || root->val >= high) return false;
    return preOrder(root->left, low, root->val) && preOrder(root->right, root->val, high);
}
bool isValidBST(TreeNode *root) {
    int tmp = INT_MIN;
    return bst(root);
}
bool bst(TreeNode *root) {
    if(root == NULL) return true;
    if(bst(root->left) == false) return false;
    if(root->val <= tmp) return false;
    tmp = root->val;
    return bst(root->right);
} 

8、判断子结构(2018)

// 注:空结点不为任何树的子结构

bool isSubStructure(TreeNode *A, TreeNode *B) {
    //当A或B为null时,返回false
    if(A == null || B == null) return false;
    //若A和B不为空,首先调用isSub方法,判断二叉树B是否为根节点与二叉树A根节点相同的子结构
    //接着判断二叉树B是不是A的左子树或者右子树的子结构
    return isSub(A,B) || isSubStructure(A->left,B) || isSubStructure(A->right,B);
}
// 判断二叉树B是否为根节点与二叉树A根节点相同的子结构
bool isSub(TreeNode *A,TreeNode *B){
    if(B == null) return true;
    if(A == null || A->val != B->val) return false;
    return isSub(A->left, B->left) && isSub(A->right, B->right);
}

9、翻转二叉树

// 自底向上(后序)
TreeNode* invertTree(TreeNode* root) {
    if (root == NULL) return NULL;
    TreeNode* left = invertTree(root->left);
    TreeNode* right = invertTree(root->right);
    root->left = right;
    root->right = left;
    return root;
}
// 思考:尝试用先序来写?
// 后序先序都可以 中序不可以?

10、二叉树宽度

//宽度:具有结点数最多的那一层的结点个数
int getWidth(TreeNode* root) {
    if(root == NULL) return 0;
    int width = 1;
    queue<TreeNode*> Q;
    Q.push(root);
    while(!Q.empty()){
        int len = Q.size();   //本层宽度
        for(int i=0; i<len; ++i){
            TreeNode *p = Q.front();
            q.pop();
            if(p->left != NULL) Q.push(p->left);
            if(p->right != NULL) Q.push(p->right);
        }
        width = width > len ? width :len;
    }
    return width;
}

11、二叉树直径

// 直径是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
// 注:2016考的是“根结点左右子树相隔最远的叶子结点之间的距离”

12、二叉树祖先问题(王道142页12、13)



免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM