我是靠谱客的博主 甜甜萝莉,最近开发中收集的这篇文章主要介绍leetcode只出现一次的数字,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

第一种解法:

思考:首先不考虑说明部分,不考虑空间复杂度和时间复杂度,看到题目中有个限制,除了唯一元素外,其他元素都均出现两次,遍历整个数组,把出现两次的元素都标记0,最后再遍历一把数组。如果全部时0,返回0;负责返回唯一一个非0.

缺点:时间复杂度高,并且改变了原数组元素的值,可以考虑把数组复制一下,但是空间复杂度会提升。

int singleNumber(int* nums, int numsSize){
    int a,i,j;

    for(i=0; i<numsSize; i++)
    {
        if(nums[i] == 0)
            continue;
        else
            a = nums[i];
        for(j = i+1; j < numsSize; j++)
        {
            if(a == nums[j])
            {
                nums[i] = 0;
                nums[j] = 0;
                break;
            }
            else
                continue;
        }
    }
    i = 0;
    while(i<numsSize && nums[i] == 0)
        i++;
    return i == numsSize ? nums[numsSize-1] : nums[i];
}

 时间复杂度:O(n*n)

空间复杂度:O(1)

第二种解法:最优解且符合题目要求

(看别人题解):妙妙妙

思考:

异或三定律:
a^a = 0;
a^0 = a;
a^b^c = a^(b^c);//异或交换律 结合律?

考虑只有一个元素只出现一次,其他均出现2次,把所有元素异或一把,搞定

int singleNumber(int* nums, int numsSize){
    int ret = 0;//一定记得初始化为0,不然可能会出现异常
    for(int i = 0; i < numsSize; i++)
        ret ^= nums[i];
    return ret;
}

第三种解法:略微复杂,且空间浪费较多,但是比较通用,不仅针对本题其他元素出现2,出现N次也可满足--leetcode 137. 只出现一次的数字 II

构建一个链表,每一个链表存储元素值及其出现次数,轮询整个数组,把每一值出现的次数存在链表中,最后再轮询链表,找到只出现一次的元素。

//这个程序中为了方便,使用链表头尾指针
typedef struct Node{
    int val;
    int count;
    struct Node *next;
}node;
//传进来的tail一定要是**,采用尾插法,需要修改尾指针的值
void insert_node(node* head, node** tail, int data)
{
    node * p = head->next;
    while(p != *tail)
    {
        if(p->val == data)
        {
            p->count++;
            return;
        }
        else
            p = p->next;
    }

    node* newnode = (node *)malloc(sizeof(struct Node));
    newnode->val = 0;
    newnode->count = 0;
    newnode->next = NULL;
    (*tail)->val = data;
    (*tail)->count++;
    (*tail)->next = newnode;
    *tail = newnode;
    return;
}
int find(node* head, node *tail)
{
    int ret;
    node *p = head;
    node *q = NULL;
    while(p != tail)
    {
        if(p->count == 1)
            ret = p->val;
        q = p->next;
        free(p);
        p = q;
    }
    free(tail);
    return ret;
}

int singleNumber(int* nums, int numsSize){

    node* head = (node *)malloc(sizeof(struct Node));
    head->val = 0;
    head->count = 0;
    node* tail = (node *)malloc(sizeof(struct Node));
    head->next = tail;
    tail->val = 0;
    tail->count = 0;
    tail->next = NULL;
    int i = 0;
    for(;i < numsSize; i++)
        insert_node(head,&tail,nums[i]);
    return find(head,tail);

}

 137题提交

第四种解法:hashmap--参考多数元素(第三种解法,我自己写的hashmap) 

第五种解法:go语言,利用map

func singleNumber(nums []int) int {
    var numsinfo map[int] int
    numsinfo = make(map[int] int)
    for i :=0 ; i < len(nums); i++ {
        numsinfo[nums[i]]++; 
    }
    for key,value := range numsinfo {
        if value == 1{
            return key;
        }
    }
    return 0;
}

一种幼稚的想法:

复制一个数组出来,然后根据对应输入数组元素的下标++,最后遍历新数组,值为1的下标返回即为只出现一次的元素

问题:输入数组 nums[] = {5},立马段错误

解决:创建一个int类型范围大小的数组,但是这个不现实,只理论可行。

int singleNumber(int* nums, int numsSize){
    int *a = (int *)malloc(numsSize*sizeof(int));
    for(int i = 0;i < numsSize; i++)
        a[i] = 0;
    for(int i = 0;i < numsSize; i++)
        a[nums[i]]++;
    for(int i = 0; i < numsSize; i++)
        if(a[i] == 1)
        {
            free(a);
            return i;
        }
    free(a);
    return 0;
}

最后

以上就是甜甜萝莉为你收集整理的leetcode只出现一次的数字的全部内容,希望文章能够帮你解决leetcode只出现一次的数字所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部