如何根据数组或者字符串创建链表?

***By Long Luo***

在[Leetcode](https://leetcode-cn.com/problemset/all/)做[链表](https://leetcode-cn.com/tag/linked-list/)相关的题时,给出的测试用例总是数组或者字符串形式,比如[61. 旋转链表](https://leetcode-cn.com/problems/rotate-list/)这道题,Testcase如下所示:

**示例 1:**

![img](https://upload-images.jianshu.io/upload_images/577271-49b58ba7650ff071.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>输入:head = [1,2,3,4,5], k = 2
>输出:[4,5,1,2,3]

# 问题

如果在本地测试代码时,每次测试代码的时候,都需要自己创建测试用例,或者调用leetcode给的例子,都需要手动去创建一个链表的话,但这样效率太低!针对这种情况,写了几个工具函数用来处理链表的代码,可供大家参考。

<!--more-->

# 测试代码

个人测试链表测试代码如下:

```java
public static void main(String[] args) {
    ListNode test1 = LinkedListUtils.constructListNode(new int[]{1, 2, 3, 4, 5});
    System.out.println("[4,5,1,2,3] ?=" + LinkedListUtils.printLinkedList(rotateRight(test1, 2)));

    ListNode test2 = LinkedListUtils.constructListNode(new int[]{0, 1, 2});
    System.out.println("[2,0,1] ?=" + LinkedListUtils.printLinkedList(rotateRight(test2, 4)));
}
```

# 打印链表

Leetcode上链表最后输出形式:

> 输出:[4,5,1,2,3]

打印方法很简单,代码如下所示:

```java
    public static String printLinkedList(ListNode head) {
        if (head == null) {
            return "[]";
        } else if (head.next == null) {
            return "[" + head.val + "]";
        }

        StringBuilder sb = new StringBuilder();
        sb.append("[");
        while (head.next != null) {
            sb.append(head.val);
            if (head != null) {
                sb.append(",");
            }
            head = head.next;
        }
        sb.append(head.val).append("]");

        return sb.toString();
    }
```

# 如何创建一个链表?

## 通过int数组创建链表

由一个给定的数组来创建一个链表,这个很简单,只需要遍历输入的数组,然后根据各个元素创建链表的节点的对象,然后把各个对象链接起来即可。

```java
    public static ListNode constructListNode(int[] numbers) {
        if (numbers == null || numbers.length == 0) {
            return null;
        }

        ListNode dummyNode = new ListNode(-1);
        ListNode preNode = dummyNode;
        for (int i = 0; i < numbers.length; i++) {
            ListNode currNode = new ListNode(numbers[i]);
            preNode.next = currNode;
            preNode = preNode.next;
        }

        return dummyNode.next;
    }
```

注意:这里使用了链表操作常用的技巧,**使用一个dummyNode作为链表的起始节点**。这样做的好处是使后面所有节点的操作完全相同,否则链表中的第一个节点的操作要特殊处理,这样可以减少冗余代码,提高效率(不同多次判断是否为头节点),并且即使为空链表,也不需要特殊考虑。

## 通过字符串创建链表

上一小节,我们实现了通过int数组得到了链表的方法,但Leetcode中还有通过字符串来构建链表,而字符串又有多种形式。总结有以下几种方式:

```txt
"1->2->3->4->5->NULL"
"1->2->3->4->5->null "
" 1->2->3->4->5"
"[1, 2, 3, 4 ,5]"
"[1, 2, 3, 4 ,5, NULL]"
"[1, 2, 3, 4 ,5, null]"

注意:
   1. 字符串前后中间可以有空格
   2. NULL为大写或小写均可
```

有了上一节构造链表的方法,我们可以先将字符串处理成整型数组,然后调用`constructListNode(int[] numbers)`来构造链表。

处理思路如下:
1. 去除字符串中全部空格;
2. 如果前后有中括号`[]`,先去除括号,再按照逗号`,`调用`split`进行分割数组;
3. 如果中间有箭头`->`,调用`split`进行分割数组;
4. 遇到最后的`NULL`或者`null`,设置为空。

代码如下所示:

```java
    public static ListNode constructListNode(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }

        String listStr = str.replaceAll(" ", "");
        String[] numbersStrArray;
        if (listStr.charAt(0) == '[' && listStr.charAt(listStr.length() - 1) == ']') {
            listStr = listStr.substring(1, listStr.length() - 1);
            numbersStrArray = listStr.split(",");
        } else if (listStr.contains("->")) {
            numbersStrArray = listStr.split("->");
        } else {
            numbersStrArray = new String[1];
            numbersStrArray[0] = listStr;
        }

        int numLength = 0;
        if (numbersStrArray.length > 1) {
            if (numbersStrArray[numbersStrArray.length - 1].equalsIgnoreCase("null")) {
                numLength = numbersStrArray.length - 1;
            } else {
                numLength = numbersStrArray.length;
            }
        } else {
            numLength = 1;
        }

        int[] numbers = new int[numLength];
        for (int i = 0; i < numLength; i++) {
            numbers[i] = Integer.parseInt(numbersStrArray[i]);
        }

        return constructListNode(numbers);
    }
```

测试代码如下:

```java
    public static void main(String[] args) {
        System.out.println(printLinkedList(constructListNode("1->2->3->4->5->NULL ")));
        System.out.println(printLinkedList(constructListNode(" 1->2->3->4->5")));
        System.out.println(printLinkedList(constructListNode(" 1->2->3->4 ->5 -> null ")));
        System.out.println(printLinkedList(constructListNode("[1, 2, 3, 4 ,5]")));
        System.out.println(printLinkedList(constructListNode("[1, 2, 3, 4 , 5, null]")));
        System.out.println(printLinkedList(constructListNode("[1,  2, 3, 4 , 5, NULL]")));
    }
```

# 小结

上述代码集成在LinkedListUtils类中,包含:
1. `printLinkedList(ListNode head)`,打印一个链表的方法;
2. 两个创建链表的方法: `constructListNode(int[] numbers)`,由整型数组创建;`constructListNode(String str)`,由字符串创建。

本文来源:[如何根据数组或者字符串创建链表?](http://www.longluo.me/blog/2020/12/10/Construct-A-LinkedList-From-An-Array-Or-String/)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以给你提供一个大概的思路和步骤,但具体的实现还需要根据你的需求和具体情况进行调整。 1. 定义数据类型和结构体 首先,你需要定义数据库支持的数据类型,例如整型、浮点型、字符串等。然后,你需要设计一个结构体来表示每个字段的属性,例如字段名、数据类型、长度等。 2. 创建数据存储结构 接下来,你需要创建一个数据存储结构,可以使用链表或二维数组来存储数据。如果数据比较简单,可以使用二维数组来存储,每一行代表一条记录,每一列代表一个字段。如果数据比较复杂,可以使用链表来存储,每个节点代表一条记录,节点中存储着该记录的各个字段的值。 3. 实现增删改查操作 接下来,你需要实现增删改查等操作。对于增加和修改操作,你需要先根据用户输入的字段名和值,判断该字段是否存在以及该值是否符合该字段的数据类型和长度要求。如果符合要求,就将该记录添加到数据存储结构中。对于删除和查询操作,你需要先根据用户输入的条件,找到符合条件的记录,然后进行删除或查询。 4. 实现用户界面 最后,你需要实现一个用户界面,通过界面让用户可以方便地进行操作。你可以使用字符串和位运算来实现用户界面,例如使用字符串来显示菜单选项和操作结果,使用位运算来处理用户输入的选项。 总之,这是一个比较复杂的项目,需要你熟悉并掌握多种知识点,才能够顺利完成。希望我的思路和步骤能够帮助到你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值