大一下考核题解

文章介绍了大一编程考核中涉及的几个算法题,包括验证回文串的处理、矩阵置零、合并两个有序链表、对链表进行插入排序、股票交易策略以及搜索插入位置和旋转链表,展示了相应的代码实现和解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大一下考核题解

125. 验证回文串

本题思路是我们要先去掉所有的非字母数字字符,然后大写转小写,再去判断正着和反着是否相同就可以了。

下面是代码:

bool isPalindrome(char* s) {
    int len = strlen(s);
    int l = 0;
    int r = 0;
    while (r < len) {
        if (s[r] >= 'A' && s[r] <= 'Z')
            s[r] = s[r] + 'a' - 'A';
        if ((s[r] >= 'a' && s[r] <= 'z') || (s[r] >= '0' && s[r] <= '9')) {
            s[l++] = s[r++];
        } else {
            r++;
        }
    }
    r = l - 1;
    l = 0;
    while (l <= r) {
        if (s[l++] != s[r--])
            return false;
    }
    return true;
}

其中我对去电非数字字母字符这一操作用了双指针的方法,左边l指针负责记录合法字符,右边r指针负责遍历完成所有的字符,遇到符合题意的就令s[l++]=s[r++],反之直接r++就可以了。这样最后0~l-1就是所有的小写字母与数字,然后再判断就可以了。

73. 矩阵置零

因为我们直接在原数组中进行修改会无法判断数组中的0是原题还是修改之后的,所以本题的最直接的思路就是我们直接重新创建一个二维数组进行标记原数组为0的位置,然后重新遍历一遍新创建的数组,当遇到之前标记的位置,我们就把数组对应的行和列全部设置为0,就可以实现本题了。

下面是代码:

void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
    int hash[201][201] = {0};
    for (int i = 0; i < matrixSize; i++) {
        for (int j = 0; j < *matrixColSize; j++) {
            if (matrix[i][j] == 0)
                hash[i][j] = 1;
        }
    }
    for (int i = 0; i < 201; i++) {
        for (int j = 0; j < 201; j++) {
            if (hash[i][j] == 1) {
                int hang = i;
                int lie = j;
                for (int p = 0; p < *matrixColSize; p++)
                    matrix[hang][p] = 0;
                for (int p = 0; p < matrixSize; p++)
                    matrix[p][lie] = 0;
            }
        }
    }
}

21. 合并两个有序链表

本题具体思路为:

  • 如果list1为空,直接返回list2;
  • 如果list2为空,直接返回list1;
  • 后面我们就需要进行递归了;
  • 如果list1数值大于list2,那么我们就需要保存此时的list2节点并且将list1与list2->next继续进行合并并且用list2->next进行接收;
  • 反之将list2与list1->next继续进行合并并用list1->next进行接收;
  • 返回list1或list2。

下面是具体代码:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;
    if (list1->val > list2->val) {
        list2->next = mergeTwoLists(list1, list2->next);
        return list2;
    } else {
        list1->next = mergeTwoLists(list1->next, list2);
        return list1;
    }
}

147. 对链表进行插入排序

本题具体思路是:

  • 先创建一个虚拟头结点方便之后的插入;
  • cur为要插入的节点,用last和pre去寻找要插入的位置,pre是前一个位置,last是后一个位置。
  • 初始化last为head,cur为head->next,用last去找比cur数值大的第一个数;
  • 然后创建pre指向newhead->next,去寻找比cur数值小的最后一个位置;
  • 进行插入,更新cur进行下一次插入。

下面是代码:

struct ListNode* insertionSortList(struct ListNode* head) {
    if (head == NULL) {
        return head;
    }
    struct ListNode* newhead = malloc(sizeof(struct ListNode));
    newhead->val = 0;
    newhead->next = head;
    struct ListNode* last = head;
    struct ListNode* cur = head->next;
    while (cur) {
        if (last->val <= cur->val) {
            last = last->next;
        } else {
            struct ListNode* pre = newhead;
            while (pre->next->val <= cur->val) {
                pre = pre->next;
            }
            last->next = cur->next;
            cur->next = pre->next;
            pre->next = cur;
        }
        cur = last->next;
    }
    return newhead->next;
}

309. 买卖股票的最佳时机含冷冻期

先来看代码:

int maxProfit(int* prices, int pricesSize) {
    if (pricesSize == 0) {
        return 0;
    }
    int f[pricesSize][3];
    f[0][0] = -prices[0];
    f[0][1] = f[0][2] = 0;
    for (int i = 1; i < pricesSize; ++i) {
        f[i][0] = fmax(f[i - 1][0], f[i - 1][2] - prices[i]);
        f[i][1] = f[i - 1][0] + prices[i];
        f[i][2] = fmax(f[i - 1][1], f[i - 1][2]);
    }
    return fmax(f[pricesSize - 1][1], f[pricesSize - 1][2]);
}

一共分为三种情况。

其中: f[i] [0]: 手上持有股票的最大收益
f[i] [1]: 手上不持有股票,并且处于冷冻期中的累计最大收益
f[i] [2]: 手上不持有股票,并且不在冷冻期中的累计最大收益

初始化第0天一种情况是买票,为-prices[0],其他情况为没买,初始化为0;

从第一天开始:

  • 对于f[i] [0],目前有的股票是在第i-1天就已经拥有的或者是第i天买入的并且第i-1天不能处于冷冻期;
  • 对于f[i] [1],我们第i天之后处于冷冻期证明我们在这一天卖出了股票,说明在第i-1天必须有一张股票;
  • 对于f[i] [2],我们在第i天结束之后不持有任何股票并且不处于冷冻期,说明第i-1天时不持有任何股票;
  • 如果处于冷冻期,对应的状态为 f[i−1] [1];如果不处于冷冻期,对应的状态为 f[i−1] [2];
  • 最后一天我们手上不能留有股票,所以最后对f[pricesSize - 1] [1], f[pricesSize - 1] [2]取最大值就可以了。

35. 搜索插入位置

本题是一道简单的二分查找题。

主要思路就是当nums[mid]>=target,令right=mid,反之令left=mid+1。

之所以将nums[mid]==target归于第一类,是因为目标数字可能不存在。把等于归于第一类,我们会在最后的情况下left和right刚好落在大于或等于目标值的第一个位置,该下标就为目标值或者插入位置。

下面是代码:

int searchInsert(int* nums, int numsSize, int target) {
    int left = 0;
    int right = numsSize;
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] >= target)
            right = mid;
        else if (nums[mid] < target)
            left = mid + 1;
    }
    return right;
}

61. 旋转链表

本题我们需要先求出链表的长度len,用k进行取模(因为移动len次相当于没有移动,反倒会增加运行时间,导致超时),然后我们需要进行循环,每一次循环都找到最后一个节点,将该节点的next指向头结点,然后将最后一个节点的前一个节点pre的next指向NULL,这样就实现了一次旋转,我们循环k次就可以了。

下面是代码:

struct ListNode* rotateRight(struct ListNode* head, int k) {
    if (head == NULL)
        return head;
    if (head->next == NULL)
        return head;
    int len = 0;
    struct ListNode* cur = head;
    while (cur) {
        cur = cur->next;
        len++;
    }
    k %= len;
    while (k--) {
        cur = head;
        struct ListNode* pre = cur;
        while (cur->next) {
            pre = cur;
            cur = cur->next;
        }
        cur->next = head;
        head = cur;
        pre->next = NULL;
    }
    return head;
}

以上就是大一下考核题解!

已经到底啦!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值