2024.06.19 刷题日记

2024-06-20 00:44
文章标签 刷题 19 日记 2024.06

本文主要是介绍2024.06.19 刷题日记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

41. 缺失的第一个正数

这个题目的通过率很低,是一道难题,类似于脑筋急转弯,确实不好想。实际上,对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1,N+1] 中。

这个结论并不好想,举个例子:nums = [3,4,-1,1],长度为 4,未出现的最小正数是 2;极端一点,nums = [1,2,3,4],未出现的最小正数是 5。因此算法的第一步就是预处理,将这个范围之外的数全部标记掉:

		for (int& num : nums) {if (num <= 0 || num > n) {num = n + 1;}}

对于 nums = [3,4,-1,1],操作之后,nums = [3,4,5,1]

第二步,需要将符合条件的数,放到它标记到应该呆的位置上,标记方法是取反,比如 1,就放到第一个位置 0,将每一个数操作一遍:

		for (int i = 0; i < n; ++i) {int pos = abs(nums[i]) - 1; // 计算原始数字对应的索引if (pos < n && nums[pos] > 0) { // 只有在正常范围内的数才进行放置nums[pos] =-nums[pos]; // 通过取负值来标记这个位置的数字已经存在}}

对于 nums = [3,4,5,1],操作之后,nums = [3,4,-5,1]nums = [3,4,-5,-1]nums = [3,4,-5,-1](不变)、nums = [-3,4,-5,-1]。经过这轮操作之后,会发现,第二个数没有被标记,因此数组中没有 2,因此将 2 返回:

		for (int i = 0; i < n; ++i) {if (nums[i] > 0) {return i + 1; // 返回缺失的第一个正数}}return n + 1; // 如果1到n都存在,那么返回n+1

73. 矩阵置零

这道题目的思路是,首先判断第一行或者第一列是否有 0 元素:

		bool firstRowZero = false;bool firstColZero = false;for (int i = 0; i < m; i++) {if (matrix[i][0] == 0) {firstColZero = true;break;}}for (int j = 0; j < n; j++) {if (matrix[0][j] == 0) {firstRowZero = true;break;}}

然后根据非第一列非第一行得元素是否为零,标记第一列或者第一行:

 		for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {if (matrix[i][j] == 0) {matrix[i][0] = 0;matrix[0][j] = 0;}}}

当第一行或者第一列被标记了,就可以根据这个信息来标记其它元素了:

		for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {if (matrix[i][0] == 0 || matrix[0][j] == 0) {matrix[i][j] = 0;}}}

最后根据flags 置第一行第一列元素为 0:

		if (firstColZero) {for (int i = 0; i < m; i++) {matrix[i][0] = 0;}}if (firstRowZero) {for (int j = 0; j < n; j++) {matrix[0][j] = 0;}}

48. 旋转图像

这个题目的思路是先转置,然后反转每一行:

class Solution {
public:void rotate(vector<vector<int>>& matrix) {int n = matrix.size();// 转置矩阵for (int i = 0; i < n; ++i) {for (int j = i; j < n; ++j) {swap(matrix[i][j], matrix[j][i]);}}// 反转每一行for (int i = 0; i < n; ++i) {reverse(matrix[i].begin(), matrix[i].end());}}
};

240. 搜索二维矩阵 II

我以为这道题要从左上角开始搜索,后来才发现必须通过右上或者坐下,因为这两个方向中,元素单调性是相反的,单调性如果相同,是没办法排除的:

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {if (matrix.empty() || matrix[0].empty())return false;int m = matrix.size();int n = matrix[0].size();int i = 0, j = n - 1;while (i < m && j >= 0) {if (matrix[i][j] == target) {return true;} else if (matrix[i][j] > target) {j--; } else {i++; }}return false; }
};

160. 相交链表

这道题目简单,直接双指针,因为 A+B = B+A,它们这样运行一圈后,必然会相交:

class Solution {
public:ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {if (headA == NULL || headB == NULL)return NULL;ListNode* pA = headA;ListNode* pB = headB;while (pA != pB) {// 如果达到末尾,则转向另一链表的头部pA = pA == NULL ? headB : pA->next;pB = pB == NULL ? headA : pB->next;}// 若相遇,则 pA 或 pB 为交点,或两者均为 NULL,未相交return pA;}
};

206. 反转链表

这个题目用两种解法,递归和迭代:

class Solution {
public:ListNode* reverseList(ListNode* head) {// 递归// if(head ==  nullptr || head->next == nullptr)// return head;// ListNode *newNode = reverseList(head->next);// head->next->next = head;// head->next = nullptr;// return newNode;// 迭代ListNode* prev = nullptr; // 前一个结点ListNode* curr = head;    // 遍历ListNode* next = nullptr; // 存储下一个结点while (curr != nullptr) {next = curr->next; // 存储下一个结点curr->next = prev; // 反转当前prev = curr;       // 移动curr = next;       // 移动}return prev;}
};

234. 回文链表

这个题目能用到上面的解法,先用快慢指针找到中点,然后反转后面的链表,然后双指针从两边向中心靠近且比较:

class Solution {
public:bool isPalindrome(ListNode* head) {if (head == nullptr || head->next == nullptr)return true;ListNode *slow = head, *fast = head, *prev = nullptr, *next = nullptr;while (fast != nullptr && fast->next != nullptr) {fast = fast->next->next;slow = slow->next;}while (slow != nullptr) {next = slow->next;slow->next = prev;prev = slow;slow = next;}ListNode* left = head;ListNode* right = prev;while (right != nullptr) {if (left->val != right->val)return false;left = left->next;right = right->next;}return true;}
};

141. 环形链表

快慢指针:

	bool hasCycle(ListNode* head) {ListNode *fast = head, *slow = head;while (fast != nullptr && slow != nullptr) {fast = fast->next;if (fast == nullptr)return false;fast = fast->next;slow = slow->next;if (slow == fast)return true;}return false;}

142. 环形链表 II

这个用哈希表简直是降维打击:

	ListNode *detectCycle(ListNode *head) {unordered_set<ListNode *> visited;while (head != nullptr) {if (visited.count(head)) {return head;}visited.insert(head);head = head->next;}return nullptr;}

21. 合并两个有序链表

使用一个伪头结点,然后将所有的结点挂在这个结点上:

class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {ListNode dummy(0); ListNode* tail = &dummy; // 使用一个尾指针,始终指向新链表的最后一个节点while (list1 && list2) {if (list1->val < list2->val) {tail->next = list1;  // 接上 list1 的当前节点list1 = list1->next; // 移动 list1 指针} else {tail->next = list2;  // 接上 list2 的当前节点list2 = list2->next; // 移动 list2 指针}tail = tail->next; // 移动尾指针到新链表的末尾}tail->next = list1 ? list1 : list2;return dummy.next; }
};

总结

41. 缺失的第一个正数

  • 利用索引作为哈希键通过元素取反来标记存在的数字,有效利用数组自身空间来存储信息。
  • 确保处理后的数组中,每个数字都在其应有的位置上,没有则是缺失的最小正数。

73. 矩阵置零

  • 使用矩阵的第一行和第一列作为标记数组,记录哪些行列需要被置零。
  • 分步处理,先标记,后置零,注意操作的顺序和逻辑清晰。

48. 旋转图像

  • 先转置矩阵,然后反转每一行,是一种简洁的在原地操作矩阵的方法,符合题目要求的空间复杂度。

240. 搜索二维矩阵 II

  • 从右上角(或左下角)开始搜索,利用行和列的单调性来排除行或列,这种策略提高了搜索效率。

160. 相交链表

  • 双指针法,一个从链表A出发到链表B,另一个从链表B出发到链表A,两者会在交点相遇。
  • 由于路径长度相同(A+B=B+A),所以两指针会同时到达交点。

206. 反转链表

  • 迭代和递归两种方式,迭代方式通过交换指针方向在原地反转链表,而递归则是通过递归栈来实现。

234. 回文链表

  • 快慢指针找到中点,反转后半部分,然后前后两部分进行比对。
  • 这种方法充分利用了链表的特性,减少了空间复杂度。

141. 环形链表

  • 快慢指针法检测环,快指针每次走两步,慢指针每次走一步,如果相遇则说明有环。

142. 环形链表 II

  • 使用哈希表记录访问过的节点,第一个重复访问的节点即为环的入口。
  • 或者使用快慢指针确定环的存在后,用两个指针从头和相遇点出发,第二次相遇点即为环的入口。

21. 合并两个有序链表

  • 使用一个伪头节点简化边界情况的处理,通过比较两链表头部节点的值,依次选择较小的节点拼接到新链表上。

这篇关于2024.06.19 刷题日记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1076619

相关文章

详解Spring Boot接收参数的19种方式

《详解SpringBoot接收参数的19种方式》SpringBoot提供了多种注解来接收不同类型的参数,本文给大家介绍SpringBoot接收参数的19种方式,感兴趣的朋友跟随小编一起看看吧... 目录SpringBoot接受参数相关@PathVariable注解@RequestHeader注解@Reque

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II 1.题目 1.1递增子序列 题目链接:491. 非递减子序列 - 力扣(LeetCode) 视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0491.%E9%80%92%E

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II 1.题目 1.1复原IP地址 题目链接:93. 复原 IP 地址 - 力扣(LeetCode) 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0093.%E5%A4%8

研1日记5

x = torch.tensor(x),numpy 转tensor 三维矩阵相加 screen -S pid 进入之前创建好的screen transpose()只能一次操作两个维度;permute()可以一次操作多维数据,且必须传入所有维度数, transpose()中的dim没有数的大小区分;permute()中的dim有数的大小区分 PyTorch 两大转置函数 trans

【笔记】数据结构刷题09

快速排序 215. 数组中的第K个最大元素 class Solution {public:int findKthLargest(vector<int>& nums, int k) {return divide(nums,0,nums.size()-1,nums.size()-k);}int divide(vector<int>& nums,int left,int right,int k)

C语言:刷题日志(1)

一.阶乘计算升级版 本题要求实现一个打印非负整数阶乘的函数。 其中n是用户传入的参数,其值不超过1000。如果n是非负整数,则该函数必须在一行中打印出n!的值,否则打印“Invalid input”。 首先,知道阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。那么我们先来个简单的阶乘计算吧。 #include<stdio.h>int Fact(int n){if (n <=

系统架构师考试学习笔记第三篇——架构设计高级知识(19)嵌入式系统架构设计理论与实践

本章考点:         第19课时主要学习嵌入式系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分)。在历年考试中,案例题对该部分内容都有固定考查,综合知识选择题目中有固定分值的考查。本课时内容侧重于对知识点的记忆、理解和应用,按照以往的出题规律,嵌入式系统架构设计基础知识点基本来源于教材内。本课时知识架构如图19.1所示。 一、嵌入式系统发展历程