LeetCode 24_Swap Nodes in Pairs

这几天真是忙的不可开交,主要是因为要学的东西太多了,本人又有完美主主义倾向,所以对于一些知识就非常浪费时间,这样做有点好处就是理解深刻,但缺点就是太费时间。话说回来,算法这种东西,是有必要深追究的,因为这是往大了说是一个创造的工作,往小了说最起码也是匹配吧。你最少得知道什么情况该用什么算法吧,如果你只是把一个算法翻译成代码(当然这也不是一个简单的工作),那你学的算法是完全没有用武之地的,甚至那根本就不叫你学的算法,你只是一个编码者罢了。

当然学习这种事不可能是一帆风顺的,你学的越多越感觉自己渺小。尤其是当你根本不理解别人那三五行的代码时。其实这就是算法的魅力,还是调整心态,放低自己,切记不要骄傲自满,觉得自己会几个简单的算法就厉害了。总有比你高得多的高人告诉你:程序,不是这么写得~

好了,废话不多说了,赶紧上题吧。

Given a linked list, swap every two adjacent nodes and return its head.

For example,
Given 1->2->3->4, you should return the list as 2->1->4->3.

Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed.

这是leetcode第24题,理解上面难度不是很大,就是给你一个链表,将里面的节点两两互换了,注意是节点交换,不能改变节点的值,说白了,就是要考察你对节点指针的运用。

怎么说呢,这其实是一个数据结构的方法实现问题。也算是一个算法吧,一个应用背景很明确的算法。主要就看你会不会被各个指针弄糊涂了。

边界条件!

指针判空!

没有头结点!

这些东西已经是重复了n遍了,别的地方可以错(当然最后别错),这些地方绝对不能再错了,否则真是无可救药了!

直接上代码吧

//Definition for singly-linked list.
  struct ListNode {
      int val;
      ListNode *next;
      ListNode(int x) : val(x), next(NULL) {}
  };
 
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
		//指针即边界条件判断
		if(head==NULL || head->next==NULL)
			return head;
		//指针定义
		ListNode* pFirst=head;
		ListNode* pSecond=head->next;
		ListNode* pThrid = NULL;
		ListNode* pForth = NULL;

		head=pSecond;//改变头指针

		while(1)
		{
			if(pFirst&&pSecond)
			{
				pThrid = pSecond->next;
				pSecond->next = pFirst;
				if(pThrid!=NULL && pThrid->next!=NULL)
				{
					pForth=pThrid->next;
					pFirst->next = pForth;
				}
				else 
				{
					pFirst->next = pThrid;
					break;
				}
			}
			pFirst=pThrid;
			pSecond=pForth;
	
		}

        return head;
    }
};

显然时间复杂度为O(n)。至于逻辑,自己一定要画个链表走一遍,这样才能明白,别人说再多没啥用。

我在开始编码时犯了一个错误,就是忘了pFirst正常情况下(即后面还有足够多元素)是应该指向pForth的,而指向了pThrid。其实也不是忘了,就是没想到这一层,所以说这种题写完代码之后如果时间允许是一定要举几个具体例子自己捋一遍的。不要把题看小了,把自己看大了。说实在的,你没有太多机会犯错误的,如果你有三次面试机会,每个面试问三道题,那就相当于你只有一次机会来做对一道题换取这份工作。错一次就什么都没有了,所以不要把调试程序当成你程序设计不可缺少的一部分,进入调试证明你已经失业!

这次写的算法不多,“没用”的说了不少,因为确实就是个细心的问题,或者说,是一个态度问题。这段时间很忙,也很茫,希望自己可以调整好。多学点儿有用的知识。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给定一个字符串,请将字符串里的字符按照出现的频率降序排列。 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2: 输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3: 输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。注意'A'和'a'被认为是两种不同的字符。 Java代码如下: ``` import java.util.*; public class Solution { public String frequencySort(String s) { if (s == null || s.length() == 0) { return ""; } Map<Character, Integer> map = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); map.put(c, map.getOrDefault(c, 0) + 1); } List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (o1, o2) -> o2.getValue() - o1.getValue()); StringBuilder sb = new StringBuilder(); for (Map.Entry<Character, Integer> entry : list) { char c = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { sb.append(c); } } return sb.toString(); } } ``` 解题思路: 首先遍历字符串,使用HashMap记录每个字符出现的次数。然后将HashMap转换为List,并按照出现次数从大到小进行排序。最后遍历排序后的List,将每个字符按照出现次数依次添加到StringBuilder中,并返回StringBuilder的字符串形式。 时间复杂度:O(nlogn),其中n为字符串s的长度。遍历字符串的时间复杂度为O(n),HashMap和List的操作时间复杂度均为O(n),排序时间复杂度为O(nlogn),StringBuilder操作时间复杂度为O(n)。因此总时间复杂度为O(nlogn)。 空间复杂度:O(n),其中n为字符串s的长度。HashMap和List的空间复杂度均为O(n),StringBuilder的空间复杂度也为O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值