牛客网刷题记录1(链表)

本文介绍了如何使用Go和PHP实现链表的从尾到头打印、反转及检测环的入口节点。对于Go代码中出现的问题,解释了`make`和`append`的用法差异,以及它们如何影响最终输出。同时,对比了两种语言在处理边界条件和错误检查上的不同策略。
摘要由CSDN通过智能技术生成

牛客网上的题

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 链表中环的入口结点

链表一定有环。快慢双指针实现。

  1. 找到快慢指针第一次相遇的位置。
  2. 快指针回到头节点,按照慢指针步速前进
  3. 第二次快慢指针相遇位置,就是入口指针

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 也是一种变量类型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J.MSh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值