个人学习编程(3-14) leetcode刷题

合并两个有序数组:

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

两种方法都是从后向前来 进行比较,然后赋值给后面的元素慢慢向前。

指针:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int i = m - 1; // nums1有效元素末尾
    int j = n - 1; // nums2末尾
    int k = m + n - 1; // 合并后数组末尾

    // 从后向前比较并填充
    while (i >= 0 && j >= 0) {
        if (nums1[i] > nums2[j]) {
            nums1[k--] = nums1[i--];
        } else {
            nums1[k--] = nums2[j--];
        }
    }

    // 处理nums2剩余元素
    while (j >= 0) {
        nums1[k--] = nums2[j--];
    }
}

这里为什么没有

// 处理nums1剩余元素
    while (i >= 0) {
        nums1[k--] = nums2[i--];
    } 

这里的代码呢? 因为nums1本身就是有序的所以不需要这个

完整代码:

#include <stdio.h>

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int p1 = m - 1, p2 = n - 1, tail = m + n - 1;
    while (p2 >= 0) { // 只需处理nums2剩余元素
        if (p1 >= 0 && nums1[p1] > nums2[p2]) {
            nums1[tail--] = nums1[p1--];
        } else {
            nums1[tail--] = nums2[p2--];
        }
    }
}

int main() {
    int m, n;
    scanf("%d %d", &m, &n);
    int nums1[200] = {0}, nums2[200] = {0};
    
    // 输入nums1有效元素
    for (int i = 0; i < m; i++) {
        scanf("%d", &nums1[i]);
    }
    // 输入nums2
    for (int i = 0; i < n; i++) {
        scanf("%d", &nums2[i]);
    }
    
    merge(nums1, m+n, m, nums2, n, n);
    
    // 输出结果
    for (int i = 0; i < m+n; i++) {
        printf("%d ", nums1[i]);
    }
    return 0;
}

冒泡排序:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    // 1. 将 nums2 追加到 nums1 尾部
    for (int i = 0; i < n; i++) {
        nums1[m + i] = nums2[i];
    }
    // 2. 整体排序(这里用冒泡排序示意,实际应调用库函数)
    for (int i = 0; i < m + n; i++) {
        for (int j = 0; j < m + n - i - 1; j++) {
            if (nums1[j] > nums1[j + 1]) {
                int temp = nums1[j];
                nums1[j] = nums1[j + 1];
                nums1[j + 1] = temp;
            }
        }
    }
}

移除元素:

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k

快慢指针:

int removeElement(int* nums, int numsSize, int val) {
    int slow = 0;
    for (int fast = 0; fast < numsSize; fast++) {
        if (nums[fast] != val) {
            nums[slow++] = nums[fast];
        }
    }
    return slow;
}

 遍历:

int removeElement(int* nums, int numsSize, int val) {
    int left = 0;  // 初始化左指针
    int right = numsSize - 1;  // 初始化右指针

    while (left <= right) {
        if (nums[left] == val) {
            // 如果左指针指向的元素等于目标值,则将右指针指向的元素移到左指针位置
            nums[left] = nums[right];
            right--;  // 右指针向左移动
        } else {
            left++;  // 否则左指针向右移动
        }
    }

    return left;  // 返回不等于val的元素个数
}

删除有序数组中的重复项:

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。
int removeDuplicates(int* nums, int numsSize) {
    if (numsSize == 0) return 0;
    int slow = 0;
    for (int fast = 1; fast < numsSize; fast++) {
        if (nums[fast] != nums[slow]) {
            slow++;
            nums[slow] = nums[fast];
        }
    }
    return slow + 1;
}

 删除有序数组中的重复项2:

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

int removeDuplicates(int* nums, int numsSize) {
    if (numsSize <= 2) return numsSize;
    int slow = 1;
    for (int fast = 2; fast < numsSize; fast++) {
        if (nums[fast] != nums[slow-1]) {
            slow++;
            nums[slow] = nums[fast];
        }
    }
    return slow + 1;
}

 

多数元素:

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入:nums = [3,2,3]
输出:3

示例 2:

输入:nums = [2,2,1,1,1,2,2]
输出:2

单层循环:

int majorityElement(int* nums, int numsSize) {
    int count;
    int times = numsSize / 2;
    for (int i = 0; i < numsSize; i++) {
        count = 0; // 每次外层循环开始时重置计数器
        for (int j = 0; j < numsSize; j++) {
            if (nums[i] == nums[j]) {
                count++;
            }
            if (count > times) {
                return nums[i];
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值