草庐IT

还在抱怨数据结构难? 一文带你搞懂如何AC算法题(2022版)

乔 巴 2024-05-10 原文

🍁🍁🍁 猛戳订阅 👉 详解数据结构专栏 👈 深度解析 🍁🍁🍁纯C
一文带你搞懂链表算法题(2022版建议收藏)

📋个人简介

  • 💬大家好,我是_奇奇,一名C/C++博主。河牧院大一在读。
  • 🔔欢迎一起交流学习
  • 💬我会将大一学的数据结构和C语言深度解析写成笔记记录下来。后期会慢慢推进。感兴趣可以订阅以下专栏。
  • 📌详解数据结构专栏🍁
  • 📌深度理解C语言专栏🍁
  • 🔑 个人主页🌳
  • 💡一个人可以走得很快,但一群人才能走得更远。

“滴水穿石 —— 非一日之功”

最近好多小伙伴来问我:“奇奇,数据结构学废了怎么办?顺序表链表好难啊,该怎么学好数据结构啊,感觉学会了,但是一做题就废了” 结合我自身学习数据结构的经历然后我也一一解答了小伙伴的问题。好多同学好像都有这么个经历,就是跟着学校的课程学数据结构,然后老师讲的快(甚至很水),课本也看不懂,最后课程结束了或者一开始做题才发现自己什么都不会,这是现在大学的普遍诟病。你没有办法改变,但可以改变自己。


学习方法

哪有什么人一天学会数据结构。
只是他们掌握了方法,学会了坚持。
学习数据结构有以下几个要点:
📌排在首位的还是画图。作为初学数据结构的人,指针各种乱指,画图才是唯一的救赎。
📌 第二就是先把基本的结构把图片转化为代码写出来。比如顺序表,无头单向链表,等结构的增删查改。
📌 排在第三位的是练习数据结构的题。练习code能力是必不可少的,做题的同时也是提高把图片转化为代码的能力。这里推荐LeetCode初级算法模块里面链表的题。
下面是十几道经典面试题,包括牛客网的,和LeetCode的。
绝对是你的必刷题,不刷完这些题,别说你懂链表。

放心,不会出现leetcode第一题都做不出来的,手把手带你玩转面试题~`

❄️不管你大一大二大三大四,还是考研,想要提升能力,做题必不可少。


❄️为了表达画图的重要性再次强烈推荐一个宝藏博主:

❄️附上大佬做的动图
这也是今天要做的题目:LeetCode206. 反转链表

当然,不用要求自己也像小姐姐一样会画这么丝滑动图。
❄️画静态图自己能看懂就好,我推荐画物理结构图。因为物理结构的图是比较容易理解的。


写在前面:以下题目建议从前往后依次食用,效果更佳哦。
因为题目难度是依次递增的

依次题目难度星数
⭐️
简单⭐️⭐️
中等⭐️⭐️⭐️
较难⭐️⭐️⭐️⭐️

❄️ 如果大家觉得文章有帮助,请给作者一波评论和收藏❄️。


这不是目录


1.移除元素⭐️

题目描述:

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

题目链接:

LeetCode27. 移除元素

❄️ 题目分析:

❄️ 因为题目要求原地移除元素,那么就不能再开辟新的空间。所以需要考虑元素的覆盖。我们可以采用双指针的方法。
❄️思路: 对于实例1:val = 3,如果fast的值不等于val,则fast的值赋给slow,fast和slow均往后移动一步。如果fast的值等于val,则只有fast往后移动一步。

❄️复杂度: 因为只遍历了一遍数组,没有开辟额外空间。所以时间复杂度为O(n),空间复杂度为O(1);

图解:

注意:循环条件左右都必须为指针的比较。指针减指针得到的是两指针之间的距离。

图解:

代码实现


int removeElement(int* nums, int numsSize, int val)
{
	int* fast = nums;
	int* slow = nums;
	//注意循环条件左右都必须为指针。
	while (fast != nums + numsSize)
	{
		if (*fast != val)
		{
			*slow = *fast;
			slow++;
			fast++;
		}
		else
		{
			fast++;
		}
	}
	//指针减指针得到的是两指针之间的距离。
	return slow-nums;
}

2. 删除有序数组中的重复项⭐️

题目描述

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

题目链接

LeetCode26. 删除有序数组中的重复项

题目分析

❄️题目给的关键词是升序排列的数组,原地删除,重复的元素。考虑双指针,快慢指针。
❄️思路:slow指针指向首元素,fast指针指向第二个元素。若slow的值等于fast的值,fast向后移动一步。否则slow先往后移动一步,把fast的值赋给slow,fast再往后移动一步。

❄️复杂度:只遍历了数组一遍,时间复杂度为O(n),空间复杂度为O(1);

代码实现

int removeDuplicates(int* nums, int numsSize)
{
	int* slow = nums;
	int* fast = nums + 1;
	while (fast < nums + numsSize)
	{
		if (*slow == *fast)
		{
			fast++;
		}
		else
		{
			slow++;
			*slow = *fast;
			fast++;
		}
	}
	return slow+ 1 -nums;
}

注意:因为fast指针移动的快,所以当fast越界时,循环结束。


3. 合并两个有序数组⭐️⭐️

题目描述

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

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

题目链接

LeetCode88. 合并两个有序数组

题目分析

❄️将nums2合并到nums1中,使合并后的数组按照升序排列。首先想到的是思想是归并排序。
❄️思路: 使用p1,p2两个指针指向最后两个数组的最后一个元素。分别比较两个元素的大小,谁大谁就放在tail位置上。然后指针依次向后挪一步。如果p1等于p2则按大于p2处理
复杂度:时间复杂度为O(n)

情况一:p2指针正常越界。

这道题难度为两颗星⭐️⭐️的原因就是因为有个特殊情况。
情况二:p1越界了,但p2还没越界。

代码实现

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 
{
	int* p1 = nums1 + m - 1;
	int* p2 = nums2 + n - 1;
	int* tail = nums1 + nums1Size - 1;
	//处理普通情况
	while (p2 >= nums2 && p1 >= nums1)
	{
		if (*p1 <= *p2)
		{
			*tail = *p2;
			p2--;
			tail--;
		}
		else
		{
			*tail = *p1;
			p1--;
			tail--;
		}
	}
	//处理特殊情况;
	while (p2 >= nums2)
	{
		*tail = *p2;
		p2--;
		tail--;
	}
}

4.移除链表元素⭐️⭐️

题目描述

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

题目链接

LeetCode203. 移除链表元素

题目分析

❄️这道题和第一题移除元素差不多。看似相同,实则不同。第一题实质是顺序表,这道题的实质是链表。
❄️链表咱们就用链表该有的做法。先把题目中的逻辑结构图转化为物理结构图。如图(后期熟悉链表的时候可以直接用逻辑结构)
❄️解释:每个节点对应一个地址,地址是我随机假设的。链表就是通过每个节点的next指针,将每个节点一次连接起来的。
思路: 要删除val是6的节点。就需要改变val的前一个节点的next指针的指向,使其指向val的next。因为链表有个缺陷就是尾删没法找到前一个节点。所以需要设置一个prev指针紧紧跟随cur用来记录前一个节点。最后需要free掉删除的节点哦。

复杂度: 时间复杂度O(n)

情况一:
初始状态prev指向空,cur指向第一个节点。


情况二:特殊情况是第一个节点的val就是6,这需要改变头指针的指向。

代码实现

struct ListNode* removeElements(struct ListNode* head, int val)
{
	struct ListNode* prev = NULL;
	struct ListNode* cur = head;
	while (cur)
	{
		if (cur->val != val)
		{
			prev = cur;
			cur = cur->next;
		}
		else
		{
		//特殊情况,当第一个节点为6时。
			if (prev == NULL)
			{
				struct ListNode* n = cur->next;
				free(cur);
				cur = n;
				head = n;
			}
			else
			{
				prev->next = cur->next;
				free(cur);
				cur= NULL;
				cur = prev->next;
			}
		}
	}
	return head;
}

5.反转链表⭐️⭐️

题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
附上可欣小姐姐画的丝滑动图

题目链接

LeetCode206. 反转链表

题目分析

❄️反转链表可以认为是把每一个节点都头插。
❄️思路: 因为要使第一个节点指向空,第二个节点指向第一个节点,第三个节点指向第二个节点。所以你必须要先保存当前节点的前一个节点。

复杂度:时间复杂度O(n)
起始位置如图

动图是接着第一步开始的。
注意:你以为这么写LeetCode官方会给你通过?当然不会。因为你要想极端情况,极端情况就是当链表为空时怎么办?当链表只有一个节点呢?
❄️ LeetCode的题目都是这样。一般情况大多数人都会写,极端情况就是淘汰那一大部分人的。所以我们每次写完都要想一下特殊情况。
LeetCode真是虾仁猪心呀。

代码实现

struct ListNode* reverseList(struct ListNode* head)
{
//当链表没有节点时。
	if (head == NULL)
	{
		return;
	}
	//普通情况
	struct ListNode* n1 = NULL;
	struct ListNode* n2 = head;
	struct ListNode* n3 = head->next;
	while (n2)
	{
		n2->next = n1;
		n1 = n2;
		n2 = n3;
		//当链表只有一个节点时。
		if(n3 != NULL)
		{
			n3 = n3->next;
		}
	}
	return n1;
}

6.链表的中间结点⭐️⭐️

题目描述

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

题目链接

LeetCode876. 链表的中间结点

题目分析

❄️什么意思呢?意思就是假如链表为1,2,3,4,5,则返回3.如果链表为1,2,3,4,则返回3。
❄️思路: 利用快慢指针。绝对是一大利器。设慢指针速度为每次走一步,快指针速度为每次走两步,那么在相同时间内。快指针的路程 = 慢指针的路程 * 2。那么当快指针走到尽头时。那么慢指针也就刚好指向了中间节点~

❄️复杂度: 只遍历了一次链表,时间复杂度为O(n).
xdm,双指针法绝不绝,绝对是yyds!!~~~。

情况一:当链表为奇数时。
情况一:当链表为偶数时
❄️将上述两个条件合二为一。综上所述,当fast != NULL && fast ->next != NULL时为这个程序的循环条件。
你以为这样就过LeetCode了吗?注意极端条件。
❄️注意:fast != NULL && fast ->next != NULL逻辑与左右两边的式子不能写反。 fast ->next && fast 这样写是错的。原因是逻辑与左操作数为假,就不会判断右操作数的真假。假设fast为空,那么会出现对空指针的解引用。

代码实现

struct ListNode* middleNode(struct ListNode* head)
{
	if (head == NULL)
	{
		return NULL;
	}
	struct ListNode* slow = head;
	struct ListNode* fast = head;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
	}
	return slow;
}

7.链表中倒数第k个结点 ⭐️⭐️

题目描述

输入一个链表,输出该链表中倒数第k个结点。

题目链接

链表中倒数第k个结点

题目分析

❄️求倒数第k个节点,想来想去想不到什么好方法,最后看了一个题解,还是双指针yyds。
❄️思路: 因为你需要求倒数第k个节点。假设为倒数第一个。我们可以用一个快慢指针。让慢指针为slow指向头结点,快指针fast为slow+1倍的next。

找倒数第1个节点

找倒数第2个节点

求倒数第k个节点呢?
若k大于链表的长度呢?
这都是一个问题!!
这是个难点,此题看似简单,但将图片转化为代码则不容易。

代码实现

struct ListNode* FindKthToTail(struct ListNode* pListHead, unsigned int k)
{
	struct ListNode* pHead = pListHead;
	int n = 0;
	//先求出链表的长度,判断k是否大于链表长度
	while (pHead)
	{
		pHead = pHead->next;
		n++;
	}
	if (k > n)
	{
		return NULL;
	}
	if (pListHead == NULL)
	{
		return NULL;
	}
	struct ListNode* slow = pListHead;
	struct ListNode* fast = pListHead;
	/确定k的位置
	while (k)
	{
		fast = fast->next;
		k--;
	}
	//快慢指针一起走
	while (fast)
	{
		slow = slow->next;
		fast = fast->next;
	}
	return slow;
}

注意:k的长度可能大于链表长度。


8.合并两个有序链表⭐️⭐️⭐️

题目描述

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

题目链接

LeetCode21. 合并两个有序链表

题目分析

❄️和第三题合并有序数组类似。图画出来后就不绕了。题不难,难的是画图。难的是注意极端条件。
说句实话:只要会画图,还能不会做吗?
❄️思路: 同第三题,可以往上翻。唯一不同的是链表无法访问前一个节点。这是链表的一大缺陷,所以需要先设置一个prev指针,记录下前一个节点。

从第三轮开始的图解。
正常情况
注意:极端情况:当其中一个链表为空时的情况
当剩余的最后一个节点时n1的节点呢?
当剩余的最后一个节点时n2的节点呢?

代码实现

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
//若其中一个链表为空。则返回另一个链表的头
	if (list1 == NULL)
	{
		return list2;
	}
	if (list2 == NULL)
	{
		return list1;
	}
	//正常情况
	struct ListNode* n1 = list1;
	struct ListNode* n2 = list2;
	struct ListNode* head = NULL;
	struct ListNode* prev = NULL;
	while (n1 && n2)
	{
		if (n1->val <= n2->val)
		{
			if (head == NULL)
			{
				head = n1;
				prev = n1;
				n1 = n1->next;
			}
			else
			{
				prev->next= n1;
				prev = n1;
				n1 = n1->next;
			}
		}
		else
		{
			if (head == NULL)
			{
				head = n2;
				prev = n2;
				n2 = n2->next;
			}
			else
			{
				prev->next= n2;
				prev= n2;
				n2 = n2->next;
			}
		}
	}
//其中一个链表为空后的后续操作。
	if (n1 == NULL)
	{
		prev->next = n2;
	}
	if (n2 == NULL)
	{
		prev->next= n1;
	}
	return head;
}

9.链表分割 ⭐️⭐️⭐️

题目描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

题目链接

牛客CM11 链表分割

题目分析

❄️这种题只能说是恶心到家了,题目也不描述清楚。也不给测试用例。
调bug也调了无数次,我直接说思路了。
只能说,一定要想极端情况,否则会一直错。
❄️思路: 先把这个链表小于x的节点和大于等于x的节点分开。
然后再连接两个链表。
❄️但是链表有个有个缺陷呀,你找不到前一个节点。所以只能先保存前一个节点。

极端场景。

代码实现

ListNode* partition(ListNode* pHead, int x) {
       	struct ListNode* n1 = NULL;
	struct ListNode* n2 = NULL;
	struct ListNode* cur = pHead;
	struct ListNode* next = NULL;
	struct ListNode* head2 = NULL;
	struct ListNode* head1 = NULL;
	while (cur)
	{
		if (cur->val < x)
		{
			if (n1 == NULL)
			{
				head1 = cur;
				n1 = cur;
				cur = cur->next;
			}
			else
			{

				n1->next = cur;
				cur = cur->next;
				n1 = n1->next;
			}
		}
		else
		{
			if (n2 == NULL)
			{
				head2 = cur;
				n2 = cur;
				cur = cur->next;
			}
			else
			{
				n2->next = cur;
				cur = cur->next;
				n2 = n2->next;
			}
		}
	}
	if (n1)
	{
		n1->next = head2;
		//恶心人的地方,极端情况
        if(n2)
        {
            n2->next = NULL;
        }
		return head1;
	}
	else
	{
		return head2;
	}
 }

10.链表的回文结构 ⭐️⭐️⭐️

题目描述

题目链接

牛客OR36 链表的回文结构

题目分析

因为要求时间复杂度为O(n),额外空间复杂度为O(1),所以考虑指针。
但是这题是牛客的较难题。明显不简单。
❄️这道题结合了前面LeetCode5,6题的思路。所以我说从前往后食用效果更佳嘛。
❄️思路:
1.先用第6题的代码找到链表的中间节点。
2.再用第5题的代码翻转中间节点后的链表。把链表分为两个链表
3.再用指针从两个链表的头部依次往后遍历查看每个节点的val是否相等。

复杂度: 找中间节点,翻转中间节点后的链表,指针从两个链表的头部依次往后遍历的时间复杂度都为O(n),所以相加也就O(3n),所以还是O(n);

找到链表的中间节点

反转slow后的链表
这种设置三个指针反转的方法较简单。

代码实现

牛客这道题没有C语言的实现。只有C++的,但是C++兼容C,所以也能用C在C++的编译器上实现。

bool chkPalindrome(struct ListNode* A) 
{
	//找出中间节点
	struct ListNode* slow = A;
	struct ListNode* fast = A;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
	}
	//反转中间节点后面的链表
	struct ListNode* cur = slow;
	struct ListNode* prev = NULL;
	struct ListNode* next = NULL;
	while (cur)
	{
	//这里先用了一个next保存cur的下一个值。
		next = cur->next;
		cur->next = prev;
		prev = cur;
		cur = next;
	}
	//比较两个链表的data值是否相等
	while (prev)
	{
		if (prev->data == A->data)
		{
			prev = prev->next;
			A = A->next;
		}
		else
		{
			return false;
		}
	}
	return true;
}

11.相交链表⭐️⭐️⭐️

题目描述

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

题目链接

LeetCode160. 相交链表

题目分析

思路: 若两个链表相交,则尾结点的地址肯定相等。
1.先判断是否相交,判断同时记录两链表的长度。若不相交返回NULL;
2.若相交,则让两指针从相对位置相同的位置开始出发,第一个地址相同的地方就是第一次相交的地方。

代码实现

struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{

	//判断两个链表是否相交,并计算链表的长度。
	struct ListNode* n1 = headA;
	struct ListNode* n2 = headB;
	int a = 1;
	int b = 1;
	while (n1->next)
	{
		n1 = n1->next;
		a++;
	}
	while (n2->next)
	{
		n2 = n2->next;
		b++;
	}
	if (n1 != n2)
	{
		return NULL;
	}
	//算出两个链表的长度之差,使从同一个地方开始走。
	struct ListNode* a1 = headA;
	struct ListNode* a2 = headB;
	int k = 0;
	if (b > a)
	{
		k = b - a;
		while (k)
		{
			a2 = a2->next;
			k--;
		}
	}
	else
	{
		k = a - b;
		while (k)
		{
			a1 = a1->next;
			k--;
		}
	}
	//找到第一个节点相同的位置。
	while (a1 != a2)
	{
		a1 = a1->next;
		a2 = a2->next;
	}
	return a1;
}

12.环形链表⭐️⭐️

题目描述

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

题目链接

LeetCode141. 环形链表

题目分析

此题没有办法让头指针依次遍历整个链表,因为链表有环,且你不知道环在哪个地方,所以你只要遍历,你就会陷入死循环!这是最难受的一点地方。
思路: 典型的追击问题。
使用快慢指针。让slow指针一次走一步,fast指针一次走两步。fast指针早晚会追上slow指针的。因为fast指针快呀。且每次都会离慢指针近一步。

  • 为什么快指针每次走两步,慢指针走一步可以?

假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。当慢指针刚进环时,可能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。
此时,两个指针每移动一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情况,因此:在满指针走到一圈之前, 快指针肯定是可以追上慢指针的,即相遇

如果链表带环则一定会在环中相遇,否则快指针率先走到链表的末尾
序号为快慢指针依次走的顺序,在-4的节点相遇。

代码实现

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

}

13.环形链表 II⭐️⭐️⭐️⭐️

题目描述

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

不允许修改 链表。

题目链接

LeetCode142. 环形链表 II

题目分析

相当于在上一个题的步骤上的升级,假如判断有环了。那么环的入口点在哪呢?
思路: 这道题就离谱了。需要证明。
结论:让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,
两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。

代码实现

代码实现容易,证明难。
只在上一题的判断有环后面加一段找第一个公共点的代码就ok了
可以看出来这些题都是循循渐进的。

struct ListNode* detectCycle(struct ListNode* head)
{
	if (head == NULL)
	{
		return NULL;
	}
	struct ListNode* slow = head;
	struct ListNode* fast = head;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
		if (slow == fast)
		{
			while (slow != head)
			{
				slow = slow->next;
				head = head->next;
			}
			return head;
		}
	}
	return NULL;

}

有关还在抱怨数据结构难? 一文带你搞懂如何AC算法题(2022版)的更多相关文章

  1. c# - 为什么在结构中使用 LINQ 时必须复制 "this"(如果我这样做可以)? - 2

    下面的代码在不可变结构中包含一个简单的LINQ查询。structPoint{staticreadonlyList</*enum*/>NeighborIndexes;//andotherreadonlyfields!publicIEnumerable<FlatRhombPoint>GetEdges(){returnfromneighborIndexinNeighborIndexes;selectGetEdge(neighborIndex);}}它不编译。Anonymousmethods,lambdaexpressions,andqueryexpressionsin

  2. c# - 使用哪一个 : Managed vs. 非托管哈希算法 - 2

    在常规C#应用程序中,哪个类用于哈希:xxxManaged或xxx(即SHA1Managed与SHA1)为什么? 最佳答案 以***Cng结尾的非托管哈希,即SHA256Cng,也会有平台限制。它们比托管替代方案快很多,但会在WindowsXP等运行时失败。如果您知道您的程序将始终在Windows7、VistaSP1或2008上运行,那么它们的性能通常会比托管版本好很多,即使有native互操作开销也是如此。如果您正在编写一个通用程序,***Managed类将更易于使用,因为它们将始终有效。

  3. c# - 在 .Net 中,出于性能原因,我什么时候应该通过引用传递结构? - 2

    在我的C#应用程序中,我有一个很大的结构(176字节),它每秒可能被传递给一个函数十万次。这个函数然后简单地获取一个指向结构的指针并将指针传递给非托管代码。函数和非托管代码都不会对该结构进行任何修改。我的问题是,我应该按值还是按引用将结构传递给函数?在这种特殊情况下,我的猜测是通过引用传递比将176个字节压入调用堆栈要快得多,除非JIT碰巧认识到该结构从未被修改(我的猜测是它无法识别这一点,因为该结构的地址传递给非托管代码)并优化代码。既然已经到了,我们还要回答更一般的情况,即函数不将结构的指针传递给非托管代码,而是对结构的内容执行一些只读操作结构。通过引用传递结构会更快吗?在这种情况

  4. c# - 如何概括我的算法以检测一个字符串是否是另一个字符串的旋转 - 2

    因此,我一直在研究各种问题来复习即将到来的面试,我遇到的一个问题是确定两个字符串是否是彼此的旋转。显然,我不是第一个解决这个问题的人。事实上,我确实发现我解决这个问题的想法似乎与thisquestion中采用的方法相似。.完全披露:我确实有一个relatedquestion在MathSE上,它从更数学的角度关注属性(尽管值得注意的是,由于那里解释的原因,我试图阐明其背后的想法的方式最终是不正确的)。想法是这样的(这类似于链接问题中采用的方法):假​​设您有一个字符串abcd和旋转cdab.显然,cd和ab是cdab的子串,但如果你将它们连接在一起,你会得到abcd.所以基本上,旋转只是

  5. c# - Dapper:映射层次结构和单一不同的属性 - 2

    我真的很喜欢Dapper的简单性和可能性。我想使用Dapper来解决我日常面临的常见挑战。这些在下面描述。这是我的简单模型。publicclassOrderItem{publiclongId{get;set;}publicItemItem{get;set;}publicVendorVendor{get;set;}publicMoneyPurchasePrice{get;set;}publicMoneySellingPrice{get;set;}}publicclassItem{publiclongId{get;set;}publicstringTitle{get;set;}public

  6. c# - 该类型出现在单个 LINQ to Entities 查询中的两个结构上不兼容的初始化中 - 2

    我正在尝试构建诸如条件查询之类的东西,以便从底层数据库中仅获取所需的数据。目前我有以下查询(工作正常)vareventData=dbContext.Event.Select(t=>new{Address=true?newAnonymousEventGetAddress{AddressLine1=t.Address.AddressLine1,CityName=t.Address.AddressCityName}:newAnonymousEventGetAddress(),});如果我把它改成varincludeAddress=true;//thiswillnormallybepas

  7. c# - 高效笛卡尔积算法 - 2

    有人可以为我演示一种比我目前使用的算法更有效的笛卡尔积算法(假设有一个)。我环顾四周并用谷歌搜索了一下,但看不到任何明显的东西,所以我可能会遗漏一些东西。foreach(intiinis){foreach(intjinjs){//Pairiandj}}这是我在代码中所做的高度简化的版本。这两个整数是查找键,用于检索一个/多个对象,并且将来自两个查找的所有对象配对成新对象。这个小代码块在一个更大更复杂的系统中成为一个主要的性能瓶颈,因为它运行的数据集规模很大。通过改进用于存储对象的数据结构和所涉及的查找,可能会减轻其中一些问题,但我认为主要问题仍然是笛卡尔积本身的计算。编辑关于我对算法的

  8. c# - 长生命周期对象的结构与类 - 2

    当您需要非常小的对象时,比如包含2个float属性,并且您将拥有数百万个不会立即被“销毁”的对象,结构是更好的选择还是类?就像在作为库的xna中,有point3s等作为结构,但如果您需要长时间保留这些值,它会不会对性能造成威胁? 最佳答案 与大多数关于结构的问题相反,这实际上似乎是对结构的一个很好的使用。如果它包含的数据是值类型,并且您将使用其中的大量数据,那么结构会很有效。一些提示:::结构不应大于16字节,否则将失去性能优势。::使结构不可变。这使用法更加清晰。例子:publicstructPoint3D{publicfloat

  9. c# - 对称密码算法之间的区别 - 2

    关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭5年前。ImprovethisquestionC#看起来有4种不同的对称加密算法:RijndaelManaged、DESCryptoServiceProvider、RC2CryptoServiceProvider和TripleDESCryptoServiceProvider。我正在寻找他们之间的更多信息。主要是他们各自的区别是什么。MSDN没有多大帮助,或者我只是累了。;)我确信它们之间各有利弊,就像任何有多种做事方式的事物一样。感谢您的任何启发。托

  10. c# - 从结构继承 - 2

    我想弄清楚我的代码有什么问题。我有这段代码:publicstructMyStructA{publicMyStructA(stringstr){myString=str;}publicstringmyString;}publicstructMyStructB:MyStructA{publicstringmyReversString;}我得到这个错误:Erroratcompiletime:Type'MyStructA'ininterfacelistisnotaninterface我不明白为什么?.net不像类那样实现结构? 最佳答案

随机推荐

  1. C# 用零填充量 - 2

    我有一个amount字段,它是数据库中的小数。我需要始终用小数点左边的10个数字和小数点后两个数字来显示此金额。例子:Amount=245.00应显示为0000000245.00此外,金额可能超过1,000或10,000,应显示为:0000001245.00和0000011245.00如何设置金额的格式,使其始终在小数点左侧具有可变金额大小的适当数量的零? 最佳答案 您应该在格式字符串中放入0。像这样。myValue.ToString("0000000000.00");这将始终为您提供小数点左侧的10位数字和右侧的两

  2. c# - 简化 if(x == 1 || x == 2) - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:C#ifstatementsmatchingmultiplevalues我经常发现自己编写的代码中变量可以是A或B,例如当我在转发器上调用OnItemDataBound时:protectedvoidrepeater_OnItemDataBound(objectsender,RepeaterItemEventArgse){if(e.Item.ItemType==ListItemType.Item||e.Item.ItemType==ListItemType.AlternatingItem){}}然后我经常想,一

  3. c# - 仅在文件不存在时才创建文件 - 2

    我只想创建一个文件,如果它不存在的话。代码如下:if(!File.Exists(fileName)){fileStreamfs=File.Create(fileName);}如果文件将在“if”到“create”之间创建,请将其打开以备竞争条件。如何避免?编辑:locks不能在这里使用,因为它是不同的进程(同一应用程序的多个实例)。 最佳答案 你也可以使用FileStreamfs=newFileStream(fileName,FileMode.OpenOrCreate);但是,您应该研究线程锁定,因为如果有多个线程试图访问您可能会遇

  4. c# - 如何在C#中设置系统属性 - 2

    如何在C#中设置系统属性。在java中我可以使用:System.setProperty("webdriver.chrome.driver","/path/to/where/you/ve/put/chromedriver.exe");如何在C#中执行此操作? 最佳答案 尝试System.Environment.SetEnvironmentVariable("webdriver.chrome.driver",@"/path/to/where/you/ve/put/chromedriver.exe")-MS

  5. c# - 为什么 CenterToScreen 方法会在光标所在的屏幕而不是具有焦点的应用程序的屏幕上使表单居中? - 2

    我正在使用VisualStudio2010、C#.NET4、WinForms。我的电脑有2个显示器。当我调用窗体的CenterToScreen方法时,窗体会在光标所在的屏幕上居中。有谁知道为什么吗? 最佳答案 来自documentation:Donotcallthisdirectlyfromyourcode.Instead,settheStartPositionpropertytoCenterScreen.TheCenterToScreenmethodusesthefollowingprioritylisttodetermineth

  6. c# - 什么是默认值,为什么不可覆盖? - 2

    在执行代码审查时,我发现可以通过使用Null对象模式来减少潜在错误的代码。然后我开始思考:如果那个业务对象的默认值是空对象而不是空引用,那不是很有用吗?由于C#提供了默认运算符,我尝试像这样重载它:publicstaticMyObjectoperatordefault(MyObjectobject){returnMyObject.Null;}这给了我错误:'预期可重载一元运算符'。在进一步挖掘时,我发现文档的一部分说default(T)是主要运算符:OverloadableOperators.当你实际点击上面页面上的default(T)时,它说default是一个关键字。最重要的是,这

  7. c# - 无法从 NHibernate.Driver.OracleDataClientDriver 创建驱动程序 - 2

    这是引发异常的代码:publicstaticclassNHibernateSessionManager{privatestaticISessionFactorysessionFactory=newConfiguration().Configure().BuildSessionFactory();publicstaticISessionGetSession(stringclientId){if(ContextSession==null)ContextSession=sessionFactory.OpenSession(newOracleIntercerptor(clientId.ToUp

  8. c# - 带有锁定文件的 FileStream - 2

    我想知道是否有可能将只读FileStream获取到锁定文件?现在,当我尝试读取锁定的文件时出现异常。using(FileStreamstream=newFileStream("path",FileMode.Open))谢谢! 最佳答案 您应该尝试另一个构造函数。它们记录在MSDN中。这个看起来像一个赌注:FileStreamConstructor(String,FileMode,FileAccess,FileShare)MSDNLink文件访问Aconstantthatdetermineshowthefilecanb

  9. c# - asp.net mvc 如何提供成功消息? - 2

    如何在asp.netmvc中提供成功消息? 最佳答案 如果您在与ViewData不同的页面上显示消息,则不会帮助您,因为它会根据每个请求重新初始化。另一方面,TempData可以存储两个请求的数据。这是一个例子:publicActionResultSomeAction(SomeModelsomeModel){if(ModelState.IsValid){//dosomethingTempData["Success"]="Successmessagetext.";returnRedirectToActi

  10. c# - 属性、索引器或动态成员访问不能作为 out 或 ref 参数传递 - 2

    这个问题在这里已经有了答案:C#propertyandrefparameter,whynosugar?(9个回答)Apropertyorindexermaynotbepassedasanoutorrefparameter(9个回答)关闭9年前。您好,我无法弄清楚这一点。我有这些结构和类。structCircle{...}classPainting{List<Circle>circles;publicList<Circle>circles{get{returncircles;}}}我正在尝试使用以下代码从绘画类外部修改其中一个圆圈:MutatePosition(r