牛客网上的题
JZ6 从尾到头打印链表
go 语言实现的时候发现了一些问题
package main
import . "nc_tools"
/*
* type ListNode struct{
* Val int
* Next *ListNode
* }
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param head ListNode类
* @return int整型一维数组
*/
func printListFromTailToHead( head *ListNode ) []int {
// write code here
var tmpArray []int
for {
if head == nil {
break
}
tmpArray = append(tmpArray,head.Val)
head = head.Next
}
arrayLen := len(tmpArray)
var outArray []int = make([]int,arrayLen)
size := arrayLen -1
for {
if size < 0 {
break
}
outArray = append(outArray,tmpArray[size])
size --
}
return outArray
}
上述代码:
输入:{1,2,3}
输出:[0,0,0,3,2,1]
当把make 去除掉时,输出为[3,2,1]
和make 和 append 的用法相关
make 为切片申请指定大小的空间,并且把元素默认初始化为0。
append 为切片追加元素,所以这就是上述问题代码,为什么会输出为[0,0,0,3,2,1]
JZ24 反转链表
使用 三个指针(pre,curr,next)记录状态
<?php
/*class ListNode{
var $val;
var $next = NULL;
function __construct($x){
$this->val = $x;
}
}*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param head ListNode类
* @return ListNode类
*/
function ReverseList( $head )
{
// write code here
//用三个指针记录前,后,当前位置。然后一个个拆解指向前指针
$preNode = NULL;
$currNode = $head;
$nextNode = $head->next;
while($currNode != NULL) {
//解绑原curr的next指针,将pre指针作为next
$currNode->next = $preNode;
//将pre指针指向当前节点
$preNode = $currNode;
//移动current 到原next指针
$currNode = $nextNode;
$nextNode = $currNode->next;
}
return $preNode;
}
go 语言实现版本:
package main
import . "nc_tools"
/*
* type ListNode struct{
* Val int
* Next *ListNode
* }
*/
/**
*
* @param pHead ListNode类
* @return ListNode类
*/
func ReverseList( pHead *ListNode ) *ListNode {
// write code here
if pHead == nil {
return pHead
}
var pPre *ListNode = nil
var pCurr *ListNode = pHead
var pNext *ListNode = pHead.Next
for {
//解绑原节点next,先将原节点next指向pre
pCurr.Next = pPre
pPre = pCurr
pCurr = pNext
if pCurr == nil {
break
}
pNext = pCurr.Next
}
return pPre
}
JZ23 链表中环的入口结点
链表一定有环。快慢双指针实现。
- 找到快慢指针第一次相遇的位置。
- 快指针回到头节点,按照慢指针步速前进
- 第二次快慢指针相遇位置,就是入口指针
php 实现:
<?php
/*class ListNode{
var $val;
var $next = NULL;
function __construct($x){
$this->val = $x;
}
}*/
function EntryNodeOfLoop($pHead)
{
// write code here
//快慢指针
$pFast = $pHead;
$pSlow = $pHead;
while(true){
$pFast = $pFast->next->next;
$pSlow = $pSlow->next;
if ($pFast == $pSlow){
break;
}
}
$pFast = $pHead;
while(true){
if ($pFast == $pSlow){
break;
}
$pFast = $pFast->next;
$pSlow = $pSlow->next;
}
return $pFast;
}
以下代码需要注意:
如果按照以下实现,头节点就是入口节点的情况时,会出错。
while(true){
$pFast = $pFast->next;
$pSlow = $pSlow->next;
if ($pFast == $pSlow){
break;
}
}
go 实现:
package main
func EntryNodeOfLoop(pHead *ListNode) *ListNode{
//快慢指针
pFast := pHead
pSlow := pHead
for {
if pFast.Next == nil || pFast.Next.Next == nil || pSlow.Next == nil {
return nil
}
pFast = pFast.Next.Next
pSlow = pSlow.Next
if pFast == pSlow {
break
}
}
if pFast == nil {
return nil
}
pFast = pHead
for {
if pFast == pSlow {
break
}
pFast = pFast.Next
pSlow = pSlow.Next
}
return pFast
}
小结
相比 php 实现 go 实现加了很多边界值判断,防止越界。php内部自己做了处理,如果指针的下一跳是空会赋值为NULL。
php 里面 null值
NULL 类型唯一可能的值就是 null。
注:NULL 自 PHP 7.2.0 起废弃,并且自 PHP 8.0.0 起被移除。 强烈建议不要使用本特性。
php 的变量都是使用zval 结构体存储:
php7 中的zval 结构体
里面有个变量type_flags 用来记录变量类型
null 也是一种变量类型