{ }codelper
删除元素P0058

删除所有相同的值

第一行给出个数 n,第二行给出 n 个整数,第三行给出整数 x。
从列表中删除所有等于 x 的值。
第一行输出剩下的个数,第二行按原顺序输出剩下的数,用一个空格隔开。
如果什么都不剩,第一行输出 0,第二行留空。
如果 x 不在列表中,列表保持不变。

输入
1 ≤ n ≤ 10,000,所有数和 x 都是 -1,000 到 1,000 之间的整数
输出
两行:剩下的个数,剩下的数(没有则为空行)
样例 1 · stdin
8
2 2 1 2 2 2 3 2
2
stdout
2
1 3
样例 2 · stdin
3
4 4 4
4
stdout
0

main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

最常见的陷阱是一边从前往后遍历一边删除。
删掉一个元素后,后面的会往前挪一格,但下标仍然加一,所以连续的 "2 2" 中第二个 2 会被跳过。
Python 的 for v in a: a.remove(v) 也因同样的原因跳过。
两种改法:把要留下的收集到新列表(Python [v for v in a if v != x],JavaScript、TypeScript a.filter(v => v !== x)),或者从后往前删。
一次删光的工具:Java list.removeIf(v -> v == x),C# list.RemoveAll(v => v == x),C++20 std::erase(a, x)(之前用 erase-remove 惯用法),C 用一个写入下标把留下的往前挪。
还有两个陷阱:JavaScript 的 a.splice(a.indexOf(x), 1) 只删一个,而 x 不存在时 indexOf 为 -1,会删掉最后一个元素。
给 Java List<Integer> 的 remove(x) 传 int,删的不是值而是第 x 个位置(按值删要写 remove(Integer.valueOf(x)))。
Craykon 解法从后往前用 a.按位置移除(i) 删除(a.移除(x) 只删一个)。

Pythonmain.py · 6 行
n = int(input())a = list(map(int, input().split()))x = int(input())rest = [v for v in a if v != x]print(len(rest))print(*rest)
JavaScriptmain.js · 5 行
const [n, ...rest] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const a = rest.slice(0, n);const x = rest[n];const left = a.filter((v) => v !== x);console.log(left.length + "\n" + left.join(" "));
TypeScriptmain.ts · 6 行
import { readFileSync } from "node:fs";const [n, ...rest]: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const a: number[] = rest.slice(0, n);const x: number = rest[n];const left: number[] = a.filter((v) => v !== x);console.log(left.length + "\n" + left.join(" "));
JavaMain.java · 19 行
import java.util.ArrayList;import java.util.List;import java.util.Scanner;import java.util.StringJoiner; public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        int n = sc.nextInt();        List<Integer> a = new ArrayList<>();        for (int i = 0; i < n; i++) a.add(sc.nextInt());        int x = sc.nextInt();        a.removeIf(v -> v == x);        StringJoiner out = new StringJoiner(" ");        for (int v : a) out.add(String.valueOf(v));        System.out.println(a.size());        System.out.println(out);    }}
C#Main.cs · 16 行
using System;using System.Collections.Generic;using System.Linq; class Program{    static void Main()    {        Console.ReadLine();        List<int> a = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList();        int x = int.Parse(Console.ReadLine());        a.RemoveAll(v => v == x);        Console.WriteLine(a.Count);        Console.WriteLine(string.Join(" ", a));    }}
C++main.cpp · 14 行
#include <iostream>#include <vector> int main() {    int n, x;    std::cin >> n;    std::vector<int> a(n);    for (int& v : a) std::cin >> v;    std::cin >> x;    std::erase(a, x);  // C++20. 그 전에는 a.erase(std::remove(a.begin(), a.end(), x), a.end());    std::cout << a.size() << "\n";    for (size_t i = 0; i < a.size(); i++) std::cout << (i ? " " : "") << a[i];    std::cout << "\n";}
Cmain.c · 16 行
#include <stdio.h> int main(void) {    static int a[10000];    int n, x, m = 0;    scanf("%d", &n);    for (int i = 0; i < n; i++) scanf("%d", &a[i]);    scanf("%d", &x);    /* 남길 것만 앞으로 당겨 쓴다: m은 다음에 쓸 자리 */    for (int i = 0; i < n; i++)        if (a[i] != x) a[m++] = a[i];    printf("%d\n", m);    for (int i = 0; i < m; i++) printf(i ? " %d" : "%d", a[i]);    putchar('\n');    return 0;}
Craykonmain.cray · 13 行
n = 控制台.读行().转数字();a = 控制台.读数字();x = 控制台.读行().转数字();// 뒤에서부터 지우면 지운 뒤 당겨지는 칸을 건너뛰지 않는다循环 (i = a.数量 - 1; i >= 0; i--){    如果 (a[i] == x)    {        a.按位置移除(i);    }}控制台.输出(a.数量);控制台.输出(a);