链倒排序头部插入写法总结

对于链倒排序写了三种:

1 原地反转法  https://blog.youkuaiyun.com/abk921/article/details/112056711

2 递归法  https://blog.youkuaiyun.com/abk921/article/details/112343925

3 头部插入法

这次实现的是头部插入法实现总结:

自己画的示意图如下:

代码是:

/**
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution
{
  public:
    ListNode *reverseList(ListNode *head)
    {
        ListNode tmp(0);
        ListNode *cur = head, * nptr = NULL;
        while (cur)
        {
            nptr = cur->next;
            cur->next = tmp.next;
            tmp.next = cur;
            cur = nptr;
        }

        return tmp.next;
    }
}

 

<think>我们有一个列表A,其中每个元素包含一个列表B(即列表B是列表A中元素的属性)。我们需要在遍历列表A时,对每个元素中的列表B进行排序,排序规则是:如果列表B中包含0,则将0全部排在最前面,其余部分升序排序;如果不包含0,则整个列表升序排序。 步骤: 1. 遍历列表A的每个元素。 2. 对于每个元素,获取其内部的列表B。 3. 判断列表B中是否包含0。 - 如果包含0,则将0全部移到最前面,然后对剩余部分进行升序排序。 - 如果不包含0,则直接对整个列表B进行升序排序。 注意:我们不应该改变原列表B中0的个数,只是将0移到前面,其他非0元素升序排列。 实现思路: 我们可以将列表B分成两部分:0和非0元素。然后对非0元素进行升序排序,最后将0的列表(可能有多个0)和非0的排序后的列表合并。 具体步骤: a. 遍历当前元素中的列表B,将0取出放入一个列表(zeros),将非0元素放入另一个列表(nonZeros)。 b. 对nonZeros进行升序排序。 c. 将zeros列表(里面可能有多个0)和排序后的nonZeros列表合并,形成新的列表B。 d. 将新的列表B赋值给当前元素的列表B(如果需要修改原列表,则进行赋值)。 注意:如果原列表B允许修改,我们可以直接修改它;如果不希望修改原对象,则需要根据情况创建新列表。这里我们直接创建新列表并赋值。 代码示例(Java): 假设我们有一个类ClassA,其中有一个属性listB(类型为List<Integer>)。 步骤: 1. 遍历List<ClassA> listA; 2. 对每个ClassA对象,操作其listB。 代码: ```java import java.util.ArrayList; import java.util.Collections; import java.util.List; class ClassA { private List<Integer> listB; public ClassA(List<Integer> listB) { this.listB = listB; } public List<Integer> getListB() { return listB; } public void setListB(List<Integer> listB) { this.listB = listB; } } public class Main { public static void main(String[] args) { // 创建测试数据 List<ClassA> listA = new ArrayList<>(); listA.add(new ClassA(new ArrayList<>(List.of(3, 0, 1, 0, 2)))); // 包含0 listA.add(new ClassA(new ArrayList<>(List.of(5, 2, 3, 1)))); // 不包含0 // 遍历listA,对每个元素的listB进行排序 for (ClassA item : listA) { List<Integer> originalList = item.getListB(); // 将0和非0分开 List<Integer> zeros = new ArrayList<>(); List<Integer> nonZeros = new ArrayList<>(); for (Integer num : originalList) { if (num == 0) { zeros.add(num); } else { nonZeros.add(num); } } // 对非零部分升序排序 Collections.sort(nonZeros); // 合并两个列表:先放0,再放非0 List<Integer> sortedList = new ArrayList<>(zeros); sortedList.addAll(nonZeros); // 重新设置listB item.setListB(sortedList); } // 输出结果验证 for (ClassA item : listA) { System.out.println("排序后的列表: " + item.getListB()); } } } ``` 输出: 排序后的列表: [0, 0, 1, 2, 3] 排序后的列表: [1, 2, 3, 5] 解释: 第一个元素中,原列表为[3,0,1,0,2],分离0得到两个0,非0部分[3,1,2]排序后为[1,2,3],然后合并[0,0]和[1,2,3]得到[0,0,1,2,3]。 第二个元素没有0,所以非零部分[5,2,3,1]排序后为[1,2,3,5]。 注意:如果列表B中可能包含null,需要额外处理。这里假设没有null。 另外,如果希望不创建新列表,而是直接在原列表上修改,可以使用以下方法: a. 先移除所有的0,然后对剩余元素排序,最后在开头添加相应数量的0。 但是这样操作可能会复杂一些,因为移除元素会改变索引。我们可以这样: ```java // 另一种方法:在原列表上修改(效率可能更高,但代码稍复杂) List<Integer> listB = item.getListB(); // 统计0的个数 int zeroCount = 0; // 使用迭代器移除0并计数 Iterator<Integer> iterator = listB.iterator(); while (iterator.hasNext()) { if (iterator.next() == 0) { iterator.remove(); zeroCount++; } } // 对剩余元素排序 Collections.sort(listB); // 在开头添加zeroCount个0 for (int i = 0; i < zeroCount; i++) { listB.add(0, 0); // 每次在头部添加0,但这样效率不高,因为每次添加都要移动整个列表 } // 或者使用以下方法:先创建一个有zeroCount个0的列表,然后把这个列表和listB合并,再赋值? // 但这样还是创建了新列表。所以如果追求效率,可以使用LinkedList,但通常ArrayList在头部插入多个元素效率低。 // 因此,我们推荐第一种方法,即创建新列表,因为清晰且对于一般大小的列表效率可以接受。 ``` 所以,我们建议使用第一种方法(分离0和非0,排序非0,合并)。 如果列表很大,且0很多,我们可以考虑使用流(Stream)来简化代码(Java 8+): ```java // 使用Stream List<Integer> sortedList = originalList.stream() .filter(num -> num != 0) // 过滤非0 .sorted() // 升序排序 .collect(Collectors.toList()); // 然后计算0的个数,在开头添加0 int zeroCount = (int) originalList.stream().filter(num -> num == 0).count(); // 创建一个包含zeroCount个0的列表 List<Integer> zeros = Collections.nCopies(zeroCount, 0); // 合并 List<Integer> newList = new ArrayList<>(zeros); newList.addAll(sortedList); ``` 这样代码更简洁,但是会遍历两次原列表(一次过滤非0并排序,一次计数0)。如果列表很大,两次遍历可能比一次遍历稍慢,但代码更清晰。 因此,我们可以根据实际情况选择。这里我们给出两种写法,供参考。 完整使用Stream的版本: ```java import java.util.*; import java.util.stream.Collectors; // ... 在遍历listA的循环中 List<Integer> originalList = item.getListB(); // 计算0的个数 long zeroCount = originalList.stream().filter(x -> x == 0).count(); // 创建非0元素的排序列表 List<Integer> nonZerosSorted = originalList.stream() .filter(x -> x != 0) .sorted() .collect(Collectors.toList()); // 创建新列表:先放0,再放排序后的非0 List<Integer> newList = new ArrayList<>(); newList.addAll(Collections.nCopies((int) zeroCount, 0)); // 添加zeroCount个0 newList.addAll(nonZerosSorted); item.setListB(newList); ``` 注意:`Collections.nCopies`返回的是一个不可变列表,所以我们需要将其加入一个可变的ArrayList中。 总结:在遍历列表A时,对其中的每个列表B,我们按照上述规则进行排序并重新赋值。 相关问题: 1. 如何对列表中的元素进行条件排序? 2. Java中如何使用Stream对列表进行筛选和排序? 3. 在Java中如何高效地将一个列表的多个元素添加到另一个列表? 4. 如何统计列表中特定元素的出现次数? 5. 在遍历列表时修改列表元素有哪些注意事项?</think>### 解决方案:在遍历列表A时对子列表B进行特殊排序 #### 核心思路 1. **分离0值和非0值**:将列表B中的元素拆分为0值和非0值两部分 2. **分别处理**: - 若有0值,将0值置于最前面 - 非0值部分进行升序排序 3. **合并结果**:将0值部分和非0值排序部分合并为新列表 #### Java实现代码 ```java import java.util.ArrayList; import java.util.Collections; import java.util.List; class ClassA { private List<Integer> listB; // 构造方法 public ClassA(List<Integer> listB) { this.listB = listB; } // Getter/Setter public List<Integer> getListB() { return listB; } public void setListB(List<Integer> listB) { this.listB = listB; } } public class SpecialListSorting { public static void main(String[] args) { // 创建测试数据 List<ClassA> listA = new ArrayList<>(); listA.add(new ClassA(new ArrayList<>(List.of(3, 0, 1, 0, 2)))); // 含0的列表 listA.add(new ClassA(new ArrayList<>(List.of(5, 2, 3, 1)))); // 不含0的列表 // 遍历列表A并处理子列表B for (ClassA item : listA) { List<Integer> originalList = item.getListB(); List<Integer> zeros = new ArrayList<>(); List<Integer> nonZeros = new ArrayList<>(); // 步骤1: 分离0值和非0值 for (Integer num : originalList) { if (num == 0) { zeros.add(num); } else { nonZeros.add(num); } } // 步骤2: 非0值部分升序排序 Collections.sort(nonZeros); // 步骤3: 合并结果 List<Integer> sortedList = new ArrayList<>(zeros); sortedList.addAll(nonZeros); // 重新赋值 item.setListB(sortedList); } // 验证结果 for (int i = 0; i < listA.size(); i++) { System.out.println("元素" + i + "排序后: " + listA.get(i).getListB()); } } } ``` #### 输出结果: ``` 元素0排序后: [0, 0, 1, 2, 3] 元素1排序后: [1, 2, 3, 5] ``` #### 关键点说明: 1. **分离处理**: - 使用两个临时列表分别存储0值(`zeros`)和非0值(`nonZeros`) - 时间复杂度:$O(n)$,其中$n$是子列表长度 2. **排序优化**: - 仅对非0部分排序,减少排序元素数量 - 使用`Collections.sort()`实现升序排序(时间复杂度$O(m \log m)$,$m$为非0元素数量) 3. **合并策略**: - 保持0值的原始顺序(若需0值也排序,可在分离后对`zeros`排序) - 使用`addAll()`高效合并列表 4. **Java 8 Stream API简化版**: ```java listA.forEach(item -> { List<Integer> listB = item.getListB(); List<Integer> sorted = listB.stream() .filter(n -> n == 0) // 先取所有0值 .collect(Collectors.toList()); sorted.addAll(listB.stream() .filter(n -> n != 0) // 再取非0值 .sorted() // 升序排序 .collect(Collectors.toList())); item.setListB(sorted); }); ``` #### 特殊情况处理: 1. **空列表检查**: ```java if (originalList == null || originalList.isEmpty()) { // 跳过处理或返回空列表 return; } ``` 2. **多条件排序**(如0值也需要排序): ```java Collections.sort(zeros); // 对0值部分排序 Collections.sort(nonZeros); // 对非0值部分排序 ``` 3. **大列表优化**: ```java // 使用并行流处理大数据集 List<Integer> sorted = listB.parallelStream() .filter(n -> n == 0) .collect(Collectors.toList()); ``` ### 总结 此方案实现了在遍历列表A时对其子列表B的特殊排序: 1. 通过分离0值和非0值实现分类处理 2. 对非0部分进行升序排序 3. 合并结果时保持0值在最前 4. 支持空值检查和大数据集优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值