在完成一个单链表的删除指定元素的题目中,我发现了一件神奇的事情,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的算法题也真的是脑力的撸铁呢。

PHP之从反向删除单链表元素的问题谈起的更多相关文章

  1. leetCode题解之删除单链表中指定的元素

    1.问题描述 Remove all elements from a linked list of integers that have value val. ExampleGiven: 1 --> ...

  2. cc150:实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针

    实现一个算法来删除单链表中间的一个结点,仅仅给出指向那个结点的指针. 样例: 输入:指向链表a->b->c->d->e中结点c的指针 结果:不须要返回什么,得到一个新链表:a- ...

  3. 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法

    有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...

  4. 删除单链表倒数第n个节点

    基本问题 如何删除单链表中的倒数第n个节点? 常规解法 先遍历一遍单链表,计算出单链表的长度,然后,从单链表头部删除指定的节点. 代码实现 /** * * Description: 删除单链表倒数第n ...

  5. 在O(1)时间内删除单链表结点

    // 在O(1)时间内删除单链表结点 /* 思考: 很显然链表是一个节点地址不连续的存储结构 删除节点一般很容易会想到是修改p节点的前一个节点的next为p->next 然而除非是双向链表,否则 ...

  6. 删除单链表节点,时间复杂度为O(1)

    一个编程练习,删除单链表一个节点,且时间复杂度控制在O(1)内. 1.核心操作代码如下: struct ListNode { int m_data; ListNode *m_pNext; }; voi ...

  7. 用O(1)的时间复杂度删除单链表中的某个节点

    给定链表的头指针和一个结点指针,在O(1)时间删除该结点.链表结点的定义如下: struct ListNode { int m_nKey; ListNode* m_pNext; }; 函数的声明如下: ...

  8. 数据结构 单链表元素定位 PTA

    由于这个很简单,他也貌似没要判断溢出,取巧突破 #include<stdio.h> #include<malloc.h> #include<stdlib.h> // ...

  9. 在O(1)时间内删除单链表结点

    给定单链表的一个结点的指针,同时该结点不是尾结点,此外没有指向其它任何结点的指针,请在O(1)时间内删除该结点. int deleteNode(LNode **head, LNode **node) ...

随机推荐

  1. android activity 启动过程分析(source code 4.4)

    说实话,android source code从2.3到4.4变化是蛮多的,尤其是media部分,虽然总的框架是没有多大变化,但是找起代码来看还是挺麻烦的.在android里面最受伤的是使用了java ...

  2. java里面的设计模式

    文章目录 Creational(创建模式) 1. Abstract factory: 2. Builder: 3. Factory: 4. Prototype: 5. Singleton: 6. Ch ...

  3. 如何成为一名高级C++程序员

     C++这门语言从诞生到今天已经经历了将近30个年头.不可否认,它的学习难度都比其它语言较高.而它的学习难度,主要来自于它的复杂性.现在C++的使用范围比以前已经少了很多,java.C#.python ...

  4. Flutter调研(2)-Flutter从安装到运行成功的一些坑

    工作需要,因客户端有部分页面要使用flutter编写,需要QA了解一下flutter相关知识,因此,做了flutter调研,包含安装,基础知识与demo编写,第二部分是安装与环境配置. —— 在mac ...

  5. 何用Java8 Stream API进行数据抽取与收集

    上一篇中我们通过一个实例看到了Java8 Stream API 相较于传统的的Java 集合操作的简洁与优势,本篇我们依然借助于一个实际的例子来看看Java8 Stream API 如何抽取及收集数据 ...

  6. [Statistics] Comparison of Three Correlation Coefficient: Pearson, Kendall, Spearman

    There are three popular metrics to measure the correlation between two random variables: Pearson's c ...

  7. Java并发编程(01):线程的创建方式,状态周期管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.并发编程简介 1.基础概念 程序 与计算机系统操作有关的计算机程序.规程.规则,以及可能有的文件.文档及数据. 进程 进程是计算机中的程序 ...

  8. EventEmitter:从命令式 JavaScript class 到声明函数式的华丽转身

    新书终于截稿,今天稍有空闲,为大家奉献一篇关于 JavaScript 语言风格的文章,主角是函数声明式. 灵活的 JavaScript 及其 multiparadigm 相信"函数式&quo ...

  9. 第八次——非确定的自动机NFA确定化为DFA

    NFA 确定化为 DFA 子集法: f(q,a)={q1,q2,…,qn},状态集的子集 将{q1,q2,…,qn}看做一个状态A,去记录NFA读入输入符号之后可能达到的所有状态的集合. 步骤: 1. ...

  10. 本地目录配置多个远程Git仓库

    目录 情景一:不同的库分别 pull/push 1. 使用git命令配置 2. 修改.git/config 文件 3. 操作 情景二:不同的库一次push 1. 使用git命令配置 2. 修改.git ...