算法(第一周)

一周周五,总结一下本周的算法学习,从本周开始重新学习许久未见的算法,当然不同于大一时使用的 C 语言以及做过的简单题,现在是每天一题 C++ 和 JavaScript(还在学,目前只写了一题)

题单是代码随想录(JS)和面试 150 题(C++), 括号中是我所用的解题语言。

令我印象最深的不是题目的难度,而是 leecode 的提交方式与我所用过的学校 oj 还有洛谷都不同,它所提交的是核心代码,一开始我都是使用 ai 帮我浓缩成核心代码样式,后面发现其实只需要补充 public 中的函数就可以了…… 我还一直在想 leecode 的输入格式到底是什么样的,话不多说开始总结:

代码随想录
移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

这题是我觉得比较简单的一道题,复习一下链表知识就好

var removeElements = function (head, val) {
  // 创建一个虚拟头节点
  const dummy = new ListNode(0);
  dummy.next = head;

  let current = dummy; // 从虚拟头节点开始遍历

  while (current.next !== null) {
    if (current.next.val === val) {
      // 跳过当前值等于 val 的节点
      //跳过了,就再也不存在这个地址,相当于删除这个元素
      current.next = current.next.next;
    } else {
      // 否则,继续移动到下一个节点
      current = current.next;
    }
  }

  // 返回新的头节点
  return dummy.next;
};

// 定义链表节点的结构
class ListNode {
  constructor(val = 0, next = null) {
    this.val = val;
    this.next = next;
  }
}

   

面试 150
多数元素

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

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

示例 1:

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

示例 2:

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

提示:

  • n == nums.length
  • 1 <= n <= 5 * 104
  • -109 <= nums[i] <= 109

进阶:尝试设计时间复杂度为 O (n)、空间复杂度为 O (1) 的算法解决此问题。

这题看上去很难,想明白了就很简单,简单来说是要找到出现最多的那个元素,但是要想明白怎么找最省力:我们假设找出一种生物,用一个计数器为 0,当这个生物遇到同类 + 1,遇到其他生物就会 - 1,当 cnt 为 0 时,说明这个生物数量不够,自然就 dead 了,以此类推,如果走到最后这个生物的数量没有为 0,则证明它是最多的一类,如果前面都不存在这种生物,那留在最后的自然而然就是最多的

class Solution {
public:
          int majorityElement(vector<int>& nums) {
        int temp;
        int cnt = 0;
            for(int i = 0; i < nums.size();i++){
                if(cnt  == 0)
                temp = nums[i];

                cnt+= (nums[i] == temp) ? +1 : -1;
            }
        return temp;
    }
};

   

合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 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 中。

提示:

  • nums1.length == m + n
  • nums2.length == n
  • 0 <= m, n <= 200
  • 1 <= m + n <= 200
  • -109 <= nums1[i], nums2[j] <= 109

这题也简单,只需要从后往前查找,比较 nums1 和 nums2 的大小,如果 nums1 大于 nums2 就往后放,反之就往前放,如果有多,nums1 未放完的自然都在前面,nums2 潍坊玩的只需要接着仿就行

#include <vector>
using namespace std;

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, 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];
                i--;
            } else {
                nums1[k] = nums2[j];
                j--;
            }
            k--;
        }

        // 将 nums2 剩余的元素复制到 nums1 中
        while (j >= 0) {
            nums1[k] = nums2[j];
            j--;
            k--;
        }
        // nums1 的剩余元素不需要复制,因为它们已经在正确的位置上
    }
};

   

罗马数字转整数

罗马数字包含以下七种字符: I, V, X, LCD 和 M

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个罗马数字,将其转换成整数。

示例 1:

输入: s = "III"
输出: 3

示例 2:

输入: s = "IV"
输出: 4

示例 3:

输入: s = "IX"
输出: 9

示例 4:

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.

示例 5:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

提示:

  • 1 <= s.length <= 15
  • s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
  • 题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999] 内
  • 题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
  • IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
  • 关于罗马数字的详尽书写规则,可以参考 罗马数字 – 百度百科。

这题需要学习一下关于 unordered_map,这里简单讲一下就是他可以存放名字+value,这样方便查找数字。思路是使用 for 循环遍历,使用 current 存储当前字母的数字,再用 next 去判断是否存在下一数字,只要存在就存入下一个字符的数字,不存在就入 0;然后进行比较,如果当前数字小于下一数字就减去当前数字,否则就加上当前数字,相等也要加上当前数字(IIII 这种情况),最后直接返回就行

class Solution {
public:
    int romanToInt(string s) {
         // 罗马数字字符与整数的映射
    unordered_map<char, int> romanMap = {
        {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50},
        {'C', 100}, {'D', 500}, {'M', 1000}
    };

    int total = 0;
    int n = s.length();

    for (int i = 0; i < n; ++i) {
        // 获取当前字符和下一个字符的数字
        int current = romanMap[s[i]];
        int next = (i + 1 < n) ? romanMap[s[i + 1]] : 0;

        // 如果当前数字小于下一个数字,执行减法
        if (current < next) {
            total -= current;
        } else {
            // 否则,执行加法
            total += current;
        }
    }

    return total;
    }
};

   

买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

提示:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 104

这题假设第一天是最低买入价格,将最大利润设置成 0(不能为负,不然不是利润),遍历数组,持续更新最低买入价格,要是比这个最低价格高就说明可能会存在最大利润,使用 max 函数比较最大利润(用当前价钱减去最低价格)

class Solution {
public:
   
 
 int maxProfit(vector<int>& prices) {
    if (prices.empty()) return 0;  // 防止空数组访问

    int minPrice = prices[0];  // 最低买入价格
    int maxProfit = 0;         // 最大利润

    for (int i = 1; i < prices.size(); i++) {
        if (prices[i] < minPrice) {
            minPrice = prices[i];  // 更新最低买入价格
        } else {
            maxProfit = max(maxProfit, prices[i] - minPrice);  // 计算当前利润
        }
    }

    return maxProfit;
}

};

   

删除有序数组中的重复项

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

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

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被 通过

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 

不需要考虑数组中超出新长度后面的元素。

   

示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

提示:

  • 1 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • nums 已按 非严格递增 排列

这题开始时我没想清楚从前开始算,这个比较应该是后一位与前一位比较,如果不相同,就将该元素赋值到一个新数组,再 cnt++,cnt 就是新数组长度(新数组是在原数组基础上添加,如果不相同那么添加的位置与原位置也相同,如果元素相同则删除一个元素,不管怎么样在原数组基础上增删都不会超过原数组长度,而且节省了空间)

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if (nums.empty()) return 0;  // 如果数组为空,返回 0

        int count = 1;  // count 用来追踪唯一元素的个数

        for (int i = 1; i < nums.size(); i++) {
            if (nums[i] != nums[i - 1]) {  // 如果当前元素和前一个不同
                nums[count++] = nums[i];   // 将当前元素移动到不重复部分的末尾
            }
        }

        return count;  // 返回不重复元素的个数
    }
};

   

移除元素

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

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

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

用户评测:

评测机将使用以下代码测试您的解决方案:

int[] nums = [...]; // 输入数组
int val = ...; // 要移除的值
int[] expectedNums = [...]; // 长度正确的预期答案。
                            // 它以不等于 val 的值排序。

int k = removeElement(nums, val); // 调用你的实现

assert k == expectedNums.length;
sort(nums, 0, k); // 排序 nums 的前 k 个元素
for (int i = 0; i < actualLength; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有的断言都通过,你的解决方案将会 通过

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2,_,_]
解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。

示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3,_,_,_]
解释:你的函数应该返回 k = 5,并且 nums 中的前五个元素为 0,0,1,3,4。
注意这五个元素可以任意顺序返回。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。

提示:

  • 0 <= nums.length <= 100
  • 0 <= nums[i] <= 50
  • 0 <= val <= 100

与代码随想录题目相同,从 js 改成了 c++

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int newLength = 0;  // 用于记录新数组的有效长度
        
        // 遍历 nums 数组
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] != val) {
                nums[newLength] = nums[i];  // 将非 val 元素放到前面
                newLength++;  // 更新新数组的长度
            }
        }
        return newLength;  // 返回新数组的长度
    }
};

   

本周题解就到这里结束,下周见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/914368.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一文了解珈和科技在农业遥感领域的服务内容和能力

2020年&#xff0c;农业农村部、中央网信办联合印发了《数字农业农村发展规划&#xff08;2019-2025年&#xff09;》&#xff0c;对数字农业农村建设作出了具体部署。其中&#xff0c;农业遥感作为推进数字农业农村的重要力量贯穿《规划》始终。 今年10月&#xff0c;农业农村…

基于STM32的智能停车场管理系统设计

引言 本项目基于STM32微控制器设计了一个智能停车场管理系统&#xff0c;通过集成多个传感器模块和控制设备&#xff0c;实现对停车位的实时监测、显示空闲车位数量&#xff0c;并通过车牌识别实现车辆的自动出入管理。该系统能够实时检测停车位的状态&#xff0c;并通过LCD屏…

springboot智慧自习室管理系统-计算机设计毕业源码96430

目录 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.1.1技术可行性 2.1.2经济可行性 2.1.3社会可行性 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 …

光流法与直接法在SLAM中的应用

本文总结视觉SLAM中常用的光流法与直接法 1、Lucas-Kanade光流法 相机所拍摄到的图像随相机视角的变化而变化&#xff0c;这种变化也可以理解为图像中像素的反向移动。“光流”&#xff08;Optical Flow&#xff09;是指通过分析连续图像帧来估计场景中像素或特征点的运动的技…

【在Linux世界中追寻伟大的One Piece】多路转接epoll

目录 1 -> I/O多路转接之poll 1.1 -> poll函数接口 1.2 -> poll的优点 1.3 -> poll的缺点 1.4 -> poll示例 1.4.1 -> 使用poll监控标准输入 2 -> I/O多路转接之epoll 2.1 -> 初识epoll 2.2 -> epoll的相关系统调用 2.2.1 -> epoll_cre…

鸿蒙华为商城APP案例

模拟器运行效果如下&#xff1a; 鸿蒙版APP-华为商城-演示视频

在公司中,如何表现出自己的高情商,学会这三句话就可以了

在职场中&#xff0c;高情商的重要性不言而喻。它能帮助你更好地处理人际关系&#xff0c;提升团队协作效率&#xff0c;还能让你在职场上获得更多的机会。 在职场中&#xff0c;适时地给予同事、上级和下属赞美、感谢和鼓励&#xff0c;能够拉近彼此的距离&#xff0c;增强团…

linux进行磁盘分区

1. lsblk查看磁盘信息 2. 进行磁盘分区 fdisk /dev/sdb 输入n 创建一个新的分区 输入p 创建一个主分区 输入1-4的一个分区号 输入开始扇地址 输入分区的大小 100G就是分100G出来 输入wq保存 3. 设置磁盘格式 /dev/sdb1为刚分出来的磁盘空间 mkfs -t ext4 /dev/sdb1 4…

边缘计算在智能物流中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 边缘计算在智能物流中的应用 边缘计算在智能物流中的应用 边缘计算在智能物流中的应用 引言 边缘计算概述 定义与原理 发展历程 …

恒创科技:什么是 RAID 3 ? RAID 3、4 和5之间有什么区别?

RAID 是一种存储数据以提高性能并减少数据丢失的特定技术。您可以根据自己的需求选择多种 RAID 类型。RAID 3 是列表中比较有效的类型之一。本文将重点介绍这种特定的 RAID 技术&#xff0c;并比较 RAID 3、4 和 5。 RAID 3 的定义 RAID 3 是一种特定的磁盘配置&#xff0c;用于…

光模块基础知识

1. 光模块的封装 光模块是光收发模块的简称&#xff0c;主要根据不同的外型来区分&#xff0c;而在同一外型中&#xff0c;又有着多种规格&#xff1b;在数据通信领域&#xff0c;最常见的光模块&#xff08;根据外型区分&#xff09;分别是SFF、GBIC、SFP、和XFP、QSFP 、XEN…

推荐一款DBF文件查看器:DBF Viewer 2000

DBF Viewer 2000是一款强大、简洁且易于使用的 DBF(Clipper、dBase、FoxBase、Foxpro、Visual Foxpro、Visual DBase、VO、DB2K)文件浏览器和编辑器。 软件特点&#xff1a; - 能够快速、有效地浏览和编辑各种类型的 DBF 文件。 - 支持多种文件格式&#xff0c;包括 dBase、V…

javascript-Web APLs (四)

日期对象 用来表示时间的对象 作用&#xff1a;可以得到当前系统时间 在代码中发现了 new 关键字时&#xff0c;一般将这个操作称为 实例化 //创建一个时间对象并获取时间 //获得当前时间 const date new Date() //获得指定时间 const date new Date(2006-6-6) console.log(…

云计算在智能交通系统中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 云计算在智能交通系统中的应用 云计算在智能交通系统中的应用 云计算在智能交通系统中的应用 引言 云计算概述 定义与原理 发展历…

图像算法之 OCR 识别算法:原理与应用场景

一、引言 在当今数字化时代&#xff0c;图像信息的处理和识别变得越来越重要。光学字符识别&#xff08;Optical Character Recognition&#xff0c;OCR&#xff09;算法作为一种能够将图像中的文字转换为可编辑文本的技术&#xff0c;正广泛应用于各个领域。从文档数字化到自…

云计算:定义、类型及对企业的影响

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 云计算&#xff1a;定义、类型及对企业的影响 云计算&#xff1a;定义、类型及对企业的影响 云计算&#xff1a;定义、类型及对企…

Chromium127编译指南 Mac篇(六)- 编译优化技巧

1. 前言 在Chromium127的开发过程中&#xff0c;优化编译速度是提升开发效率的关键因素。本文将重点介绍如何使用ccache工具来加速C/C代码的编译过程&#xff0c;特别是在频繁切换分支和修改代码时。通过合理配置和使用这些工具&#xff0c;您将能够显著减少编译时间&#xff…

打假官方咨询(续)

大家还记得我们的上一次测试吗&#xff1a;9.9大还是9.11大&#xff0c;我又把这个问题拎了出来&#xff0c;看一下各家AI的最新表现&#xff1a; 商量&#xff08;出自商汤科技&#xff09;&#xff1a; 我们可以发现&#xff0c;商量好像没长记性&#xff0c;上次错了&#…

AFL++实战入门与afl-fuzz流程解析(源码流程图)

简介 本项目为模糊测试的零基础教学,适合了解 pwn 且会使用 Linux 的 gcc、gdb 的读者。模糊测试旨在通过向程序投喂数据使其崩溃,从而获取崩溃样本以寻找程序漏洞。本文前半部分介绍 AFL++ 的 docker 环境配置,帮助读者解决入门时的环境和网络问题; 后半部分全面解析 afl…

单体架构 IM 系统之长轮询方案设计

在上一篇技术短文&#xff08;单体架构 IM 系统之核心业务功能实现&#xff09;中&#xff0c;我们讨论了 “信箱模型” 在单体架构 IM 系统中的应用&#xff0c;“信箱模型” 见下图。 客户端 A 将 “信件” 投入到客户端 B 的 “信箱” 中&#xff0c;然后客户端 B 去自己的 …