牛客刷题日记【删除有序链表中重复的元素-I|删除有序链表中重复的元素-II|二分查找-I】

BM15 删除有序链表中重复的元素-I

删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次
例如:
给出的链表为1→1→21→1→2,返回1→21→2.
给出的链表为1→1→2→3→31→1→2→3→3,返回1→2→31→2→3.

数据范围:链表长度满足 0≤n≤1000≤n≤100,链表中任意节点的值满足 ∣val∣≤100∣val∣≤100

进阶:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

思考:

顺序遍历链表,并保留第一个不同元素,若相同则把该元素删除

代码:

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
        // write code here

        ListNode* pre = head;
        // int prenum = pre->val;
        if (head == nullptr) return nullptr;

        ListNode* cur = head->next;

        while (cur) {
            if (cur->val == pre->val) {
                ListNode* tmp = cur->next;
                pre->next = tmp;
                cur = tmp;
            }
            else {
                pre = cur;
                cur = cur->next;
            }
        }

        return head;
    }
};

BM16 删除有序链表中重复的元素-II

给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
例如:
给出的链表为1→2→3→3→4→4→51→2→3→3→4→4→5, 返回1→2→51→2→5.
给出的链表为1→1→1→2→31→1→1→2→3, 返回2→32→3.

数据范围:链表长度 0≤n≤100000≤n≤10000,链表中的值满足 ∣val∣≤1000∣val∣≤1000

要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

进阶:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

思考:

用空间换时间的思路,建一个数组,把所有出现过的数字存进去,然后遍历数组,将所有值唯一的数组下标加入链表中

代码:

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
        // write code here

        int n = 2000;
        int a[n+2];//0-1000 1001-2001
        for (int i = 0;i <= n+2;i++) a[i] = 0;

        ListNode* p = head;

        while (p) {
            if (p->val >= 0)    a[p->val]++;
            if (p->val < 0)     a[1000 - p->val]++;
            p = p->next;
        }

        ListNode* res = new ListNode(-1);
        p = res;

        // -50 = 1050 ;-21 = 1021
        // -
        for (int i = 2000;i >= 1001;i--) {
            if (a[i] == 1) {
                ListNode* tmp = new ListNode(1000-i);
                p->next = tmp;
                p = p->next;
            }
        }

        // +
        for (int i = 0;i <= 1000;i++) {
            if (a[i] == 1) {
                ListNode* tmp = new ListNode(i);
                p->next = tmp;
                p = p->next;
            }
        }

        return res->next;

    }
};

BM17 二分查找-I

请实现无重复数字的升序数组的二分查找

给定一个 元素升序的、无重复数字的整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标(下标从 0 开始),否则返回 -1

数据范围:0≤len(nums)≤2×1050≤len(num**s)≤2×105 , 数组中任意值满足 ∣val∣≤109∣val∣≤109

进阶:时间复杂度 O(log⁡n)O(logn) ,空间复杂度 O(1)O(1)

思考:

基础的二分查找,用递归的方式实现,注意终止条件

代码:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型vector 
     * @param target int整型 
     * @return int整型
     */

    int Bin(vector<int>& nums, int L, int R, int tar) {
        int mid = (L+R) / 2;
        // if (L == R) {
        //     return nums[mid] == tar ? mid : -1;
        // }
        if (L > R) return -1;
        if (nums[mid] == tar) return mid;
        else {
            if (nums[mid] > tar)    return Bin(nums,L,mid-1,tar);
            if (nums[mid] < tar)    return Bin(nums,mid+1,R,tar);
        }
        return -1;
    }
    
    int search(vector<int>& nums, int target) {
        // write code here
        if (nums.size() == 0) return -1;

        return Bin(nums, 0, nums.size(), target);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值