剑指offer之从尾到头打印链表(最浅显易懂)

从尾到头打印链表 之 “C++代码+思路解析 ”

下一篇 从尾到头打印链表 (第二种情况 允许原地打印链表)

希望我的文字始终给您带来画面感。

其实做算法题的过程也是在考验我们的大脑日常解决问题的能力,懂不懂得将生活中碰到的难题拆分,一一解决

今日感悟

做算法题不要过分依赖于自己旧的的知识库,独立的把它看做一道新鲜的算法题。千万不要一碰到陌生的知识点就丢失信心。做新的算法题一定会涉及到不熟悉的数据结构知识和语法问题,把它当做工具先使用,有时间的话再去了解它是什么,不要在认识它的本质上浪费一分一秒的时间。

题目开始咯!

  题目描述:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

//这里敲黑板,千万注意:我们做算法题 ,最基本的也是最关键的题目一定要 理解准确。这道题涉及到允不允许原地修改链表,所以分为以下两种情况。

 第一种情况:不允许原地修改链表,如果不允许原地修改链表,
 那么可以利用栈后进先出的特点,遍历链表,逐个将链表元素放入栈中,
 然后依次弹出栈顶元素并打印。

代码实现部分:

//5月8日
struct ListNode {
	int val;
	struct ListNode* next;
	ListNode(int x) :
		val(x), next(NULL) {
	}//这里不懂为什么这么写,没关系
};
class Solution {
public:
	vector<int> printListFromTailToHead( ListNode* head ){
		vector<int> res;
		if ( !head )
			return res;
		//我写代码定义一般先不写,后面需要用到就把它加上。
		stack<int> sta;    
		ListNode* p = head;//指针就记着在内存里面给这个变量p分配一块地址,跟变量一样使用。
		while ( p )
		{
			sta.push( p->val );//循环里面最关键的是push这个动作
			p = p->next;
		}
		while ( !sta.empty() )
		{
			int a = sta.top();
			sta.pop();
			res.push_back(a);
		}

		return res;
   }
};

思路解析部分:

我不知道大家的写算法思路是思维习惯和先后顺序是怎样的,我会习惯将代码拆分成小的代码块进行 ,再进行逻辑组合安装。当然这里无法评判哪种一定是正确的,这里我想分享一下:我个人认为最快的写代码顺序。

第一步:我会先搞清楚题目 ,需要我给它一个什么,定下来整体的框架。

比如这道题它要我给它返回一个 数组。一个装着链表中倒序值的数组。那么 返回值类型返回语句
心里就有个概念了。还要搞清楚我们这道题需要的数组选择用静态的还是动态,动态就用vector

那第一步函数整体的框架就出来咯!

vector< int > printListFromTailToHead(..........{
vector< int > res;
................................
return res;
}

第二步:我会把参数定下来,进到函数体首先就检查参数合不合法。

加入 if 语句检验参数 链表指针 head 是否为空。

vector< int > printListFromTailToHead( ListNode* head ){
vector< int > res;
//加入这块代码检验参数。
if( !head )
{
 return res;
}
................................
return res;
}

第三步:给框架里面填上语句块。发挥( if,while,for…)语句的作用,语句其实就是思考逻辑的实现。

这道题的逻辑就是把链表的数值一个一个倒进栈里,再从栈一个一个倒入新的容器里,拿到这个容器就OK了。

1 填入 这块代码,使用while 语句,把链表里的值一个一个推到栈里。

vector< int > printListFromTailToHead( ListNode* head ){
vector< int > res;
if( !head )
{
 return res;
}
//加入这块代码向栈里推数值
...............................//这里要加定义
while ( p )
{
    sta.push( p->val );//循环里面最关键的是push这个动作
	p = p->next;
}

................................
return res;
}


2 再填入一块代码,继续使用while语句,把栈里的值一个一个弹出来,再一个一个推到容器里面。

vector< int > printListFromTailToHead( ListNode* head ){
vector< int > res;
if( !head )
{
 return res;
}
//加入这块代码向栈里推数值
...............................//这里要加定义
while ( p )
{
    sta.push( p->val );//循环里面最关键的是push这个动作
	p = p->next;
}
//加入这块代码,把栈里的值一个一个弹出来,再一个一个推到容器里面。
while ( !sta.empty() )
		{
			int a = sta.top();
			sta.pop();
			res.push_back(a);
		}
return res;
}

第四步:抠细节,扣语句块里的细节,没定义的变量要给定义。对象要使用什么函数来实现,组装起来。

1 给对象加上定义。

while ( p )
{
    sta.push( p->val );//循环里面最关键的是push这个动作
	p = p->next;
}

while语句循环检验的这个指针p ,要在前面加上定义。
sta 是一个栈变量,它是一个数据的临时存放容器,继续补上定义。

ListNode* p = head;
stack<int> sta;  

这就知道了p指向的是传进来的链表head的头结点,sta是一个栈变量。

2 使用函数 top() ,pop(), push_back(),也就是组装动作。

while ( !sta.empty() )
		{
			int a = sta.top();
			sta.pop();
			res.push_back(a);
		}

总结:

我做算法题是先搞清楚题意,安排总框架,然后把解决办法拆分成一个个步骤,再把每个步骤落实到代码块,最后填充细节。

这样可以保证算法题做下来的整个过程中我们的整个思路是清晰的,不会让看似复杂的算法在我们的大脑中留下坏印象,使我们丧失兴趣。

其实做算法题的过程也是在考验我们的大脑日常解决问题的能力,懂不懂得将生活中碰到的难题拆分,一一解决。

下一篇 从尾到头打印链表(第二种情况 允许原地打印链表)

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值