力扣考核题解

 新手代码,如有可优化的地方,还请指出

目录

矩阵置零

【题目详情】 

【思路】

【代码实现】

连续字符

【题目详情】

【思路】

【代码实现】

对链表进行插入排序

【题目详情】

【思路】

【代码实现】

 最长公共前缀

【题目详情】​编辑

【思路】 

【代码实现】

 排列硬币

【题目详情】

【思路】

【代码实现】

验证回文串

【题目详情】

【思路】

【代码实现】

合并两个有序链表

【题目详情】

【思路】

【代码实现】

心得感悟总结 


矩阵置零

【题目详情】 

【思路】

  1. 定义一个和矩阵列大小相等的列数组col,一个和矩阵行大小相等的行数组row,并将两个数组内所有元素置零,便于后续对矩阵中为0的元素的行和列进行标记。
  2. 再用两个for循环(外层为i,内层为j)进行遍历矩阵,并将矩阵中为0的元素的行和列进行标记,即令row[i]和col[j]等于1。
  3. 再次双重for循环遍历矩阵,当数组行或数组列中的元素为1时,则将矩阵中对应的元素置零。

【代码实现】

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

连续字符

【题目详情】

【思路】

  1. 先通过strlen()函数得到字符串长度。
  2. 遍历字符串,当字符串出现连续相同时,让用于计数的count++,直到遍历到与前一个字母不相同的字符为止。
  3. 再用fmax()函数记录最大值,最后将其返回即可。

【代码实现】

int maxPower(char* s) {
    int len = strlen(s);
    int max = 1;
    int count = 1;
    int arr[501] = {0};
    for (int i = 0; i < len - 1; i++) {
        if(s[i] == s[i + 1]) {
            count++;
            max = fmax(count, max);
        } else {
            count = 1;
        }
    }
    return max;
}

对链表进行插入排序

【题目详情】

【思路】

  1. 要对该题中的链表使用插入排序,我们先创建一个虚拟头结点并进行初始化,便于寻找链表的头结点。
  2. 定义一个尾指针,令其指向目前的头结点,随后定义一个新的指针cur进行遍历链表,当所指向的结点内的数据大于尾结点时,则证明在目前结点位置之前都是从小到大有序的;当cur所指的结点内的数据小于尾结点时,则设置一个指针pre从头开始遍历链表,直到pre所指结点内的数据大于cur所指结点内的数据,就找到了cur所指结点该插入的位置。然后让尾结点等于cur所指结点的下一个,让cur所指结点的下一个为pre所指结点的下一个,让pre所指结点的下一个为cur所指结点,即完成了插入。
  3. 最后从虚拟结点的下一个开始返回即可。

【代码实现】

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* insertionSortList(struct ListNode* head) {
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummy->val = 0;
    dummy->next = head;
    struct ListNode* tail;
    tail = head;
    if (head == NULL || head->next == NULL) {
        return head;
    }
    struct ListNode* cur = tail->next;
    while (cur) {
        if (cur->val >= tail->val) {
            tail = tail->next;
        } else {
            struct ListNode* pre;
            pre = dummy;
            while (pre->next->val <= cur->val) {
                pre = pre->next;
            }
            tail->next = cur->next;
            cur->next = pre->next;
            pre->next = cur;
        }
        cur = tail->next;
    }
    return dummy->next;
}

 最长公共前缀

【题目详情】

【思路】 

我们以第一个字符串作为参考靠标准,只需要将后面的字符串与第一个进行挨个字符的比较即可。

两个for循环套用,外层用来遍历第一个字符串,内层用来遍历与的一个字符串内的字符所对应的其它字符串内的字符,若不相等,则令此处第一个字符串内的元素为‘\0’(字符串终止符)并返回第一个字符串。

【代码实现】

char* longestCommonPrefix(char** strs, int strsSize) {
    if (strsSize == 0) {
        return "";
    }
    for (int i = 0; i < strlen(strs[0]); i++) {
        for (int j = 1; j < strsSize; j++) {
            if (strs[0][i] != strs[j][i]) {
                strs[0][i] = '\0';
                return strs[0];
            }
        }
    }
    return strs[0];
}

 排列硬币

【题目详情】

【思路】

 本题我使用的是暴力解法。

1. 由题我们可以得出,放置的硬币为以1为首项,以1为公差的等差数列,则第i阶放置的硬币数为       i,前i阶放置的硬币数一共为(1+i)*i/2。

2. 在放置硬币的总和小于题目所给硬币总数n之前,让i一直自增,随后判断放置的硬币总数是否与n相等,相等则返回i;否则给返回i-1(即最后一个阶梯未放满)。

【代码实现】

int arrangeCoins(int n){
    long int i = 1;
    long int total = 0;
    while (total < n) {
        i++;
        total = (1 + i) * i / 2;
    }
    if (total == n) return i;
    return i - 1;
}

验证回文串

【题目详情】

【思路】

 总的思路是开辟新数组,将处理后的字符串放入新数组后再判断是否为回文字符串。

1. 遍历字符串并进行分类讨论。如果字符的ASCLL值在‘a’~‘z’,则为小写字母,直接放入新数组,同时让新数组下标自增;如果字符的ASCLL值在‘A’~‘Z’,则为大写字母,令其减去‘A’再加上‘a’,即可转化为小写字母,然后放入新数组,同时让新数组下标自增;如果如果字符的ASCLL值在‘0’~‘9’,则为数字,直接放入新数组,同时让新数组下标自增。这样既完成了保留小写字母和数字,将大写字母转化为小写字母,又实现了去除其他字符。

2. 然后对新数组进行回文判断,即由两头向中间进行遍历比较,若有不相等的则返回false,全都相等就返回true。

【代码实现】

bool isPalindrome(char * s) {
    int i, j = 0, k;
    int l = strlen(s);
    for (i = 0; i < l; i++) {
        if (s[i] >= 'a' && s[i] <= 'z') {
            s[j] = s[i];
            j++;
        } else if (s[i] >= 'A' && s[i] <= 'Z') {
            s[j] = s[i] + 'a' - 'A';
            j++;
        } else if (s[i] >= '0' && s[i] <= '9'){
            s[j] = s[i];
            j++;
        }
    }
    s[j] = '\0';
    for (k = 0; k < j / 2; k++) {
        if (s[k] != s[j - 1 - k]) {
            return false;
        }
    }
    return true;
}

合并两个有序链表

【题目详情】

【思路】

 总的思路就是在遍历两链表的同时,对两指针所指向的链表结点内的值进行比较,并以从小到大的顺序放入新链表中。

1. 先讨论特殊情况,即当有一方链表为空时,则可以直接返回另一个链表。

2. 创建新的链表用于储存排序后的结点。在遍历两链表并进行排序时需分类讨论,当用于遍历两链表的两指针均不为空时,比较两指针指向的结点内的值的大小,将小的值连在新链表的尾部,并后移已经被放入新链表的结点对应的指针,直到有一方链表的指针指向空后,直接将另一链表的剩余结点连在排好序的新链表尾部。

3. 最后从新链表头结点的下一个开始返回链表即可。

【代码实现】

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if (!list1) {
        return list2;
    }
    if (!list2) {
        return list1;
    }
    struct ListNode* L = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode* p1 = list1, * p2 = list2; 
    struct ListNode* s = L;
    while (p1 && p2) {
        if (p1->val <= p2->val) {
            s->next = p1;
            s = p1;
            p1 = p1->next;
        } else {
          s->next = p2;
          s = p2; 
          p2 = p2->next;
        }
    } 
    if (!p1) {
        s->next = p2; 
    }
    if (!p2) {
        s->next = p1;
    } 
    return L->next;
}

心得感悟总结 

       通过这次考核,我发现自己对链表的掌握还是不够熟练,对于不同类型的链表题没法很好的运用已学的链表知识进行代码实现,需要多做题来加强巩固。 对于有思路却没做对的题,很多时候是把想法转换成代码的能力欠缺,还需多加练习并在平时做题时不断进行总结。 对于有些题,我的解法较为繁琐和暴力,在以后的学习中,不能只追求把题做出来,也要去学习别人的好的做题思路和解法,将别人的代码理解了,慢慢转化成自己的代码。 最后还有做题时的逻辑,有时候会因为考虑情况不够周全而导致部分情况下代码出错或发生栈溢出、数组越界等,还需在后续的学习中多思考,培养逻辑能力,提高逻辑缜密性。

       总之,在学编程时,要多独立思考,多刷题的同时也要不断进行总结归纳。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值