当前位置: 首页 > news >正文

leetcode热题100(2)

leetcode-73-矩阵置零

法一:两个标记数组分别记录每一行和每一列是否有零出现

时间复杂度O(mn)   空间复杂度O(m+n)

void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
    int m = matrixSize;
    int n = matrixColSize[0];
    int row[m], col[n];
    memset(row, 0, sizeof(row));
    memset(col, 0, sizeof(col));
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (!matrix[i][j]) {
                row[i] = col[j] = true;
            }
        }
    }
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (row[i] || col[j]) {
                matrix[i][j] = 0;
            }
        }
    }
}

法二:使用两个标记量

可以用矩阵的第一行和第一列代替方法一中的两个标记数组,以达到O(!)的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含0,因此需要额外使用两个标记量分别记录第一行和第一列是否原本包含0

时间复杂度O(mn)    空间复杂度O(1)

void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
    int m = matrixSize;
    int n = matrixColSize[0];
    int flag_col0 = false, flag_row0 = false;
    for(int i = 0 ; i < m ; i++){
        if(!matrix[i][0])
            flag_col0 = true;
    }
    for(int j = 0 ; j < n ; j++){
        if(!matrix[0][j])
            flag_row0 = true;
    }
    for(int i = 1 ; i < m ; i++){
        for(int j = 1 ; j < n ; j++){
            if(!matrix[i][j])
                matrix[i][0] = matrix[0][j] = 0;
        }
    }
    for(int i = 1 ; i < m ; i++){
        for(int j = 1 ; j < n ; j++){
            if(!matrix[i][0] || !matrix[0][j])
                matrix[i][j] = 0;
        }
    }
    if(flag_col0){
        for(int i = 0 ; i < m ;i++){
            matrix[i][0] = 0;
        }
    }
    if(flag_row0){
        for(int j = 0 ; j < n ; j++){
            matrix[0][j] = 0;
        }
    }
}

leetcode-48-旋转图像

转置+按列翻转

void rotate(int** matrix, int matrixSize, int* matrixColSize) {
    int temp;
    int n = matrixSize;
    for(int i = 0 ; i < n ; i++){
        for(int j = i ; j < n ; j++){
            if(i == j) continue;
            temp = matrix[i][j];
            matrix[i][j] = matrix[j][i];
            matrix[j][i] = temp;
        }
    }
    for(int j = 0 ; j < n/2 ; j++){
        for(int i = 0 ; i< n ; i++){
            temp = matrix[i][j];
            matrix[i][j] = matrix[i][n-j-1];
            matrix[i][n-j-1] = temp;
        }
    }
}

leetcode-240-搜索二维矩阵II

1.二分查找

由于矩阵每行都是升序的,所以可以依次遍历每行进行二分查找

时间O(mlogn)  空间O(1)

int binarySearch(int* nums, int size, int target){
    int l = 0, r = size-1;
    while(l <= r){
        int mid = (l+r)/2;
        if(nums[mid] > target){
            r = mid-1;
        }
        else if(nums[mid] < target){
            l = mid+1;
        }
        else{
            return mid;
        }
    }
    return -1;
}

bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
    int index;
    for(int i = 0; i < matrixSize ; i++){
        index = binarySearch(matrix[i],matrixColSize[i],target);
        if(index >= 0)
            return true;
    }
    return false;
}

2.Z字形查找

从矩阵右上角matrix[i][j]开始寻找

若matrix[i][j] > target  列--

若matrix[i][j] < target  行++

时间O(m+n)  空间O(1)

bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {
    int m = matrixSize, n = matrixColSize[0];
    int i = 0, j = n - 1; 
    while (i < m && j >= 0) { 
        if (matrix[i][j] == target) {
            return true; 
        }
        if (matrix[i][j] < target) {
            i++; 
        } else {
            j--; 
        }
    }
    return false;
}

leetcode-160-相交链表

1.两个链表相交

设headA和headB的长度分别是m和n。假设headA不相交部分有a个节点,headB不相交部分有b个节点,两个链表相交部分有c个节点,则 a+c = m, b+c = n

(1)若a = b,则两个指针会同时到达两个链表相交部分,此时返回相交节点

(2)若a 不等于 b,则指针pA遍历完headA,然后指向headB,指针pB遍历完headB,然后指向headA,然后两个指针继续移动,在指针pA移动了a+c+b次,指针pB移动了b+c+a次之后,两个指针会同时达到相交节点

2.两个链表不相交

设headA和headB的长度分别是m和n。考虑当m等于n 和 m不等于n

(1)若m 等于 n,则两个指针会同时到达链尾,返回NULL

(2)若m 不等于 n,由于链表没有公共节点,两个指针不会同时到达链尾,因此两个指针都会遍历完两个链表,在指针pA移动了m+n次,指针pB移动了n+m次后,两个指针都会同时变为NULL

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if(headA == NULL || headB == NULL)
        return NULL;
    struct ListNode *pA = headA, *pB = headB;
    while(pA != pB){
        pA = pA == NULL ? headB : pA->next;
        pB = pB == NULL ? headA : pB->next;
    }
    return pA;
}

2.getLen求不带头结点的链表长度

int getLen(struct ListNode* head){
    int len = 1;
    struct ListNode* p = head;
    while(p != NULL){
        p = p->next;
        len++;
    }
    return len;
}

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    int lenA = getLen(headA);
    int lenB = getLen(headB);
    struct ListNode *pA, *pB;
    for(pA = headA ; lenA > lenB ; lenA--){
        pA = pA->next;
    }
    for(pB = headB ; lenA < lenB ; lenB--){
        pB = pB->next;
    }
    while(pA != NULL && pA != pB){
        pA = pA->next;
        pB = pB->next;
    }
    return pA;
}

leetcode-234-回文链表

双指针:

找到链表的中间结点,将链表的后半部分翻转后,再从链表中间结点开始,与链头两两相比较,若不相同,则返回false

bool isPalindrome(struct ListNode* head) {
    if(head == NULL)
        return true;
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummy->next = head;
    struct ListNode *p = dummy, *q = dummy;
    while(q != NULL && q->next != NULL){
        p = p->next;
        q = q->next->next;
    }
    //将链表从中间断开 q指向后半部分的头部 p指向前半部分尾部
    q = p->next;  
    p->next = NULL;
    
    //将后半部分翻转
    while(q != NULL){
        struct ListNode* tmp = q->next;
        q->next = p->next;
        p->next = q;
        q = tmp;
    }
    
    //前后开始两两比较
    q = p->next;
    p = dummy->next;
    while(q != NULL){
        if(p->val != q->val)
            return false;
        p = p->next;
        q = q->next;
    }
    return true;
}

leetcode-21-合并两个有序链表

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if (list1 == NULL || list2 == NULL)
    return list1 != NULL ? list1 : list2;
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode *tmp, *tmp1;
    struct ListNode *p, *q;
    if(list1->val > list2->val){
        tmp = list1;
        list1 = list2;
        list2 = tmp;
    }
    dummy->next = list1;
    p = dummy;
    q = list2;
    while(p != NULL && q != NULL){
        while(p->next != NULL && p->next->val < q->val){
            p = p->next;
        }
        tmp = p->next;
        p->next =q;
        p = q;
        q = tmp;
    }
    return dummy->next;
}

2.

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if(list1 == NULL || list2 == NULL)
        return list1 != NULL ? list1 : list2;
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode *pre, *p, *q;
    pre = dummy;
    p = list1;
    q = list2;
    while(p != NULL && q != NULL){
        if(p->val <= q->val){
            pre->next =p;
            pre =pre->next;
            p = p->next;
        }
        else if(p->val > q->val){
            pre->next = q;
            pre = pre->next;
            q = q->next;
        }
        
    }
    if(p != NULL){
        pre->next = p;
    }
    if(q != NULL){
        pre->next = q;
    }
    return dummy->next;
}

leetcode-25-k个一组翻转链表

struct ListNode* move(struct ListNode* node, int n){
    while(node != NULL && n > 0){
        node = node->next;
        n--;
    }
    return node;
}

struct ListNode* reverseKGroup(struct ListNode* head, int k) {
    struct ListNode *p, *q, *pre, *tmp, *link;
    bool flag = true;
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummy->next = head;
    p = q = link = dummy->next; 
    while(q != NULL){
        q = move(q,k-1);
        if(q == NULL)
            break;
        pre = q->next;
        while(pre != q){
            tmp = p->next;
            p->next = pre;
            pre = p;
            p = tmp;
        }
        if(flag){
            dummy->next = q;
            flag = false;
        }else{
            link->next = q;
        }
        link = q;
        link = move(link,k-1);
        q = p;
    }
    return dummy->next;
}

2.k一组翻转

3.用栈

leetcode-2-两数相加

考虑以下情况:

1.list1 比 list2 长  list2相加完后仍有进位

2.list2 比 list1 长  list1相加完后仍有进位

3.list1 和 list2 一样长,相加完后仍有进位

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    int count;
    struct ListNode *p, *q, *pre;
    struct ListNode *dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    count = 0;
    p = l1, q = l2, pre = dummy;
    while(p != NULL || q != NULL){
        struct ListNode *node = (struct ListNode*)malloc(sizeof(struct ListNode));
        node->next = NULL;
        int n1 = p != NULL ? p->val : 0;
        int n2 = q != NULL ? q->val : 0;
        node->val = (n1 + n2 + count)%10;
        count = (n1 + n2 + count)/10;
        pre->next = node;
        pre = node;
        if(p != NULL){
            p = p->next;
        }
        if(q != NULL){
            q = q->next;
        }
    }
    if(count != 0){
        struct ListNode *node = (struct ListNode*)malloc(sizeof(struct ListNode));
        node->next = NULL;
        node->val = count;
        pre->next = node;
    }
    return dummy->next;
}

leetcode-138-随机链表的复制

leetcode-148-排序链表

 归并法

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


struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode dummy; 
    struct ListNode* cur = &dummy; 
    while (list1 && list2) {
        if (list1->val < list2->val) {
            cur->next = list1; 
            list1 = list1->next;
        } else { 
            cur->next = list2; 
            list2 = list2->next;
        }
        cur = cur->next;
    }
    cur->next = list1 ? list1 : list2; 
    return dummy.next;
}

struct ListNode* sortList(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    struct ListNode* head2 = middleNode(head);
    head = sortList(head);
    head2 = sortList(head2);
    return mergeTwoLists(head, head2);
}

leetcode-23-合并k个升序链表

leetcode-146-LRU缓存

leetcode-543-二叉树的直径

一条路径的长度为该路径经过的节点数减一,所以求直径(即求路径长度的最大值)等效于求路径经过节点数的最大值减一。

而任意一条路径均可以被看作由某个节点为起点,从其左儿子和右儿子向下遍历的路径拼接得到 

假设我们知道对于该节点的左儿子向下遍历经过最多的节点数 L (即以左儿子为根的子树的深度) 和其右儿子向下遍历经过最多的节点数 R (即以右儿子为根的子树的深度),那么以该节点为起点的路径经过节点数的最大值即为 L+R+1 。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

int getDeep(struct TreeNode* root, int* ans){
    if(root == NULL)
        return 0;
    int left = getDeep(root->left,ans);
    int right = getDeep(root->right,ans);
    *ans = fmax(*ans,left+right+1);
    return fmax(left,right)+1;
}

int diameterOfBinaryTree(struct TreeNode* root) {
    int ans = 1;
    getDeep(root,&ans);
    return ans-1;
}

leetcode-662-二叉树最大宽度

leetcode-124-二叉树最大路径和

 leetcode-437-路径总和III

leetcode-230-二叉搜索树第k小元素

int kthSmallest(struct TreeNode* root, int k) {
    struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*)*10000);
    int* res = (int*)malloc(sizeof(int)*10000);
    struct TreeNode* node = root;
    int stk_top = 0;
    int index = 0;
    while(node != NULL || stk_top > 0){
        while(node != NULL){
            stk[stk_top++] = node;
            node = node->left;
        }
        node = stk[--stk_top];
        res[index++] = node->val;
        node = node->right;
    }
    return res[k-1];
}

leetcode-144-二叉树展开为链表

void flatten(struct TreeNode* root) {
    struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*)*10000);
    struct TreeNode** res = (struct TreeNode**)malloc(sizeof(struct TreeNode*)*10000);
    int stk_top, index;
    stk_top = 0, index = 0;
    struct TreeNode* node = root;
    while(node != NULL || stk_top > 0){
        while(node != NULL){
            stk[stk_top++] = node;
            res[index++] = node;
            node = node->left;
        }
        node = stk[--stk_top];
        node = node->right;
    }
    for(int i = 0 ; i < index ; i++){
        res[i]->left = NULL;
        res[i]->right = NULL;
    } 
    for(int i = 0 ; i < index-1 ; i++){
        res[i]->right = res[i+1];
    }
}

leetcode-124-二叉树中最大路径和

http://www.dtcms.com/a/108536.html

相关文章:

  • 在Linux系统上深入安装与配置Redis:从基础到高级的全方位指南
  • LeetCode BFS解决最短路问题
  • 深入浅出:Spring Bean 的初始化流程详解
  • [力扣每日一练]关于特定字符串的匹配
  • Flutter 插件 百度地图 Android插件演示
  • 配置Next.js环境 使用vscode
  • 多元守护,构筑健康生活
  • ClickHouse与Doris对比:数据处理领域的“华山论剑”
  • 制作cass高程点块定义——cad c#二次开发
  • 在QGIS中将矢量数据导出为JSON
  • 运营商在网状态查询API接口如何对接?
  • 【Axure高保真原型】动态柱状图
  • Redis中set数据类型的内部编码及使用场景
  • 5、vim编辑和shell编程【超详细】
  • TypeScript基础教程
  • 第二章:chrony服务器
  • LLM面试题二
  • 高通camx IOVA内存不足,导致10-15x持续拍照后,点击拍照键定屏无反应,过一会相机闪退
  • SpringMVC响应数据:页面跳转与回写数据
  • 蓝桥杯最后十天冲刺 day 2 双指针的思想
  • TortoiseSVN设置忽略清单
  • 新零售系统是什么样的?有什么好处?
  • Links for llama-cpp-python whl安装包下载地址
  • WEB安全--SQL注入--上传webshell的其他方式
  • QT_xcb 问题
  • java问题
  • 《Viewport:解析与优化,提升网页体验的关键要素》
  • ETLCloud是如何通过Oracle实现CDC的?
  • Elasticsearch 报错index_closed_exception
  • JavaScript Array(数组)