从尾到头打印链表

    紧接着又练习了一个链表的操作——从尾到头打印链表。

    牛客网AC地址:http://www.nowcoder.com/books/coding-interviews/d0267f7f55b3412ba93bd35cfa8e8035?rp=1

    《剑指offer》面试题5:从尾到头打印链表

    题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。

    链表的节点定义如下:

public class ListNode {
	int val;
	ListNode next = null;

	ListNode(int val) {
		this.val = val;
	}
}

    查看牛客网给出的一些代码:

import java.util.ArrayList;
public class Solution {
    public ArrayList printListFromTailToHead(ListNode listNode) {
    	
    }
}

    思路:

    这里就借助ArrayList来实现,由于给出的是单链表,所以遍历的时候,得到的是正序;

    但是ArrayList可认为是“数组”,可以倒序遍历

    所以,我们一边遍历单链表,一边存入一个临时的ArrayList;然后倒序遍历这个临时的ArrayList,将数据转存过来,这样就相当于倒序遍历了。

    AC代码:(注意:有一点觉得很奇怪,之前放上了打印数据的代码结果一直是答案错误,去掉之后就通过了。——下面注释掉的代码)

   

public class Solution {
	public ArrayList printListFromTailToHead(ListNode listNode) { // 返回新链表的头结点
		ArrayList newHead = new ArrayList();
		ArrayList temp = new ArrayList();
		while (listNode != null) { // 遍历链表将节点的val放入ArrayList
			temp.add(listNode.val);
			listNode = listNode.next;
		}
		// 遍历ArrayList (倒叙遍历),将数据加入到newHead中
		for (int i = temp.size() - 1; i >= 0; --i) {
			newHead.add(temp.get(i));
			/*if (i == 0) {
				System.out.println(temp.get(i));
			} else {
				System.out.print(temp.get(i) + ",");
			}*/
		}
		//System.out.println();
		return newHead;
	}
}

    下面补充,《剑指offer》上,使用栈和递归实现的思路。

    使用栈的情况:

   题目要求,从尾到头遍历单链表。也就是第一个遍历到的节点要最后一个输出,最后一个遍历到的节点第一个输出。这就是典型的“后进先出”,由此可借助栈实现这种顺序。
每经过一个结点的时候,把该结点放到一个栈中。
   当遍历完整个链表后,再从栈顶开始逐个输出结点的值,此时输出的结点的顺序已经反转过来了。

void PrintListReversingly_Iteratively(ListNode* pHead) {
    std::stack nodes;

    ListNode* pNode = pHead;
    while (pNode != NULL) {
        nodes.push(pNode);
        pNode = pNode->m_pNext;
    }

    while (!nodes.empty()) {
	pNode = nodes.top();
        printf("%d\t", pNode->m-nValue);
        nodes.pop();
    }
}
    其中,单向链表的结点定义如下:

struct ListNode {
    int m_nValue;
    ListNode* m_pNext;
};

   

    使用递归:

    递归在本质上就是一个栈结构。

    要实现反过来输出链表,我们每访问到一个结点的时候,先递归输出它后面的结点,再输出该结点自身,这样链表的输出结果就反过来了。

void PrintListReversingly_Recursively(ListNode* pHead) {
    if (pHead != NULL) {
        if (pHead->m_pNext != NULL) {
            PrintListReversingly_Recursively(pHead->m_pNext);
        }
        printf("%d\t", pHead->m_nValue);
    }
}
    但有个问题:当链表非常长的时候,就会导致函数调用的 层级很深,从而有可能导致函数调用栈溢出。

你可能感兴趣的:(面试读物,Java,算法学习,链表,链表遍历)