zoukankan      html  css  js  c++  java
  • PHP之从反向删除单链表元素的问题谈起

    在完成一个单链表的删除指定元素的题目中,我发现了一件神奇的事情,php对象赋值给另外一个变量后,可以如同引用传值一般继续利用新的变量来实现链表的链接。
    后面经过查证后发现:

    PHP7.0版本除了对象,资源之外,其余数据类型均已实现写时复制

    尝试写了一个简单测试代码,如下所示:

    <?php
    
    $obj1 = new stdClass();
    $obj1->val = 3;
    $obj1->next = null;
    
    $obj2 = $obj1;
    
    $obj2->next = array();
    
    $obj2 = null;
    
    var_dump($obj1);
    

    打印出的$obj1的结构里面不会因为$obj2被赋值为null而让$obj1成为null。

    关于从后往前面删除单链表元素的问题,原题如下:

    给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

    示例:

    给定一个链表: 1->2->3->4->5, 和 n = 2.

    当删除了倒数第二个节点后,链表变为 1->2->3->5.
    说明:

    给定的 n 保证是有效的。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list

    分析下来就是一个基础单链表操作的变种题目,如果是从头往后删除的话,就是我们常见的删除操作。所以唯一不同的就是顺序问题,于是先定义获取单链表长度的函数和删除指定位置元素的函数,然后再调用的时候把从后往前的位置数改为从头往后数的位置即可。

    /**
     * Definition for a singly-linked list.
     * class ListNode {
     *     public $val = 0;
     *     public $next = null;
     *     function __construct($val) { $this->val = $val; }
     * }
     */
    class Solution {
    
        /**
         * @param ListNode $head
         * @param Integer $n
         * @return ListNode
         */
        function removeNthFromEnd($head, $n) {
            $length = getLength($head);
            $from_start_num = $length - $n;
            // if ($n == 1 && $length == 1) {
            //     return null;
            // }
            // if ($from_start_num == 0 && $n === $length) {
            //     return $head->next;
            // }
            
            $return_node_list = deleteLinkItem($head, $from_start_num);
            return $return_node_list; 
        }
    }
    
    
    /**
     * @param $head
     * @param int $index
     * @return null
     */
    function deleteLinkItem($head, $index = 1) {
        if (is_null($head)) {
            return null;
        } else {
            if ($index == 0) {
                return $head->next;
            }
            $i = 1;
            
            $current = $head;
            while($current->next != null) {
                if ($i == $index) {
                    $tmp = $current->next;
                    break;
                }
                $i++;
                $current = $current->next;
            }
    
            $current->next = $tmp->next;
    
    
            return $head;
        }
    
    }
    
    /**
     * @param $head
     * @param $node
     * @param int $index
     * @return mixed
     */
    function getLength($head) {
        if (empty($head)) {
            return 0;
        }
        $i = 1;
        while($head->next != null) {
            $i++;
            $head = $head->next;
        }
    
        return $i;
    }
    

    唯一要注意的是,由于deleteLinkItem的$index是从1开始算的,和脚标起始0不同,假如是要删除0下标(也就链表是第一个元素被删除),那么直接返回头部节点的next即可,如代码中的这段:

    if ($index == 0) {
        return $head->next;
    }
    

    总的来说解法中规中矩,没有利用的PHP的黑魔法。越是自由度高的编程语言,对于算法题来说越难真正锻炼到,所以往往需要自废神功,当成静态语言去玩。而下标看得让人脑仁疼,看来即使是一道medium的算法题也真的是脑力的撸铁呢。

  • 相关阅读:
    Silverlight日记:动态操作Grid
    【转】cocos2dx 自学知识点之三 自定义动画 使用plist来实现
    Cocos2d-x的内存管理
    好色之徒
    freetype
    cocos2d 自定义字体
    cocos2d-x 内存管理
    VS2010 检查内存泄露的方法
    c++链表
    c/c++ time.h 那点事
  • 原文地址:https://www.cnblogs.com/freephp/p/12593774.html
Copyright © 2011-2022 走看看