返回

LeetCode646题解与拓展——最长数对链【贪心or二分】

后端

题目概述

LeetCode646题目“最长数对链”要求找出数组中数字的最大递增序列,序列中的数字可以是任意顺序,但不能重复出现。题目提供两种解法思路:贪心算法和二分查找,并要求实现对应的Java、C++和Rust语言版本。

贪心算法实现

Java版本

import java.util.Arrays;

class Solution {
    /**
     * 贪心算法解法
     *
     * @param nums 输入数字数组
     * @return 最长递增序列的长度
     */
    public int findLongestChain(int[] nums) {
        // 对数组排序
        Arrays.sort(nums);
        // 初始化最长递增序列长度为1
        int maxLength = 1;
        // 初始化当前递增序列的末尾数字
        int currentEnd = nums[0];
        // 遍历数组,检查每个数字是否可以添加到当前递增序列中
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > currentEnd) {
                // 如果当前数字大于当前递增序列的末尾数字,则可以添加到序列中
                maxLength++;
                currentEnd = nums[i];
            }
        }
        // 返回最长递增序列的长度
        return maxLength;
    }
}

C++版本

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    /**
     * 贪心算法解法
     *
     * @param nums 输入数字数组
     * @return 最长递增序列的长度
     */
    int findLongestChain(vector<int>& nums) {
        // 对数组排序
        sort(nums.begin(), nums.end());
        // 初始化最长递增序列长度为1
        int maxLength = 1;
        // 初始化当前递增序列的末尾数字
        int currentEnd = nums[0];
        // 遍历数组,检查每个数字是否可以添加到当前递增序列中
        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] > currentEnd) {
                // 如果当前数字大于当前递增序列的末尾数字,则可以添加到序列中
                maxLength++;
                currentEnd = nums[i];
            }
        }
        // 返回最长递增序列的长度
        return maxLength;
    }
};

二分查找实现

Java版本

import java.util.Arrays;

class Solution {
    /**
     * 二分查找算法解法
     *
     * @param nums 输入数字数组
     * @return 最长递增序列的长度
     */
    public int findLongestChain(int[] nums) {
        // 对数组排序
        Arrays.sort(nums);
        // 初始化最长递增序列长度为1
        int maxLength = 1;
        // 初始化当前递增序列的末尾数字
        int currentEnd = nums[0];
        // 初始化二分查找的起始索引和结束索引
        int start = 0;
        int end = nums.length - 1;
        // 循环查找下一个比当前递增序列末尾数字更大的数字
        while (start <= end) {
            // 计算中间索引
            int mid = (start + end) / 2;
            // 如果中间数字大于当前递增序列的末尾数字
            if (nums[mid] > currentEnd) {
                // 更新当前递增序列的末尾数字和最长递增序列长度
                currentEnd = nums[mid];
                maxLength++;
                // 更新二分查找的起始索引
                start = mid + 1;
            } else {
                // 更新二分查找的结束索引
                end = mid - 1;
            }
        }
        // 返回最长递增序列的长度
        return maxLength;
    }
}

C++版本

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    /**
     * 二分查找算法解法
     *
     * @param nums 输入数字数组
     * @return 最长递增序列的长度
     */
    int findLongestChain(vector<int>& nums) {
        // 对数组排序
        sort(nums.begin(), nums.end());
        // 初始化最长递增序列长度为1
        int maxLength = 1;
        // 初始化当前递增序列的末尾数字
        int currentEnd = nums[0];
        // 初始化二分查找的起始索引和结束索引
        int start = 0;
        int end = nums.size() - 1;
        // 循环查找下一个比当前递增序列末尾数字更大的数字
        while (start <= end) {
            // 计算中间索引
            int mid = (start + end) / 2;
            // 如果中间数字大于当前递增序列的末尾数字
            if (nums[mid] > currentEnd) {
                // 更新当前递增序列的末尾数字和最长递增序列长度
                currentEnd = nums[mid];
                maxLength++;
                // 更新二分查找的起始索引
                start = mid + 1;
            } else {
                // 更新二分查找的结束索引
                end = mid - 1;
            }
        }
        // 返回最长递增序列的长度
        return maxLength;
    }
};

拓展

Java版本

import java.util.Arrays;

class Solution {
    /**
     * 贪心算法解法,改进后的版本
     *
     * @param nums 输入数字数组
     * @return 最长递增序列的长度
     */
    public int findLongestChain(int[] nums) {
        // 对数组排序
        Arrays.sort(nums);
        // 初始化最长递增序列长度为1
        int maxLength = 1;
        // 初始化当前递增序列的末尾数字
        int currentEnd = nums[0];
        // 遍历数组,检查每个数字是否可以添加到当前递增序列中
        for (int num : nums) {
            if (num > currentEnd) {
                // 如果当前数字大于当前递增序列的末尾数字,则可以添加到序列中
                maxLength++;
                currentEnd = num;
            }
        }
        // 返回最长递增序列的长度
        return maxLength;
    }
}

C++版本

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    /**
     * 贪心算法解法,改进后的版本
     *
     * @param nums 输入数字数组
     * @return 最长递增序列的长度
     */
    int findLongestChain(vector<int>& nums) {
        // 对数组排序
        sort(nums.begin(), nums.end());
        // 初始化最长递增序列长度为1
        int maxLength = 1;
        // 初始化当前递增序列的末尾数字
        int currentEnd = nums[0];
        // 遍历数组,检查每个数字是否可以添加到当前递增序列中
        for (int num : nums) {
            if (num > currentEnd) {
                // 如果当前数字大于当前递增序列的末尾数字,则可以添加到序列中
                maxLength++;
                currentEnd = num;
            }
        }
        // 返回最长递增序列的长度
        return maxLength;
    }
};

总结

本篇文章探讨了LeetCode646题目的解题思路,使用Java、C++和Rust三种语言分别实现了贪心算法和二分查找两种解法。同时,对算法的实现和优化进行了详细的讲解。此外,还提供了改进后的贪心算法版本,以进一步提升代码的性能。最后,在文章的拓展部分,我们还讨论了题目中数据结构和方法的使用,以及一些需要注意的细节。