读一读

给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。

示例 1:
输入: [3,0,1]
输出: 2
示例 2:
输入: [9,6,4,2,3,5,7,0,1]
输出: 8


//排序后检查
public int MissingNumber(int[] nums) {
    Array.Sort(nums);
    if(nums.Length == 0 || nums[0] == 1) return 0;
    for(int i = 0;i<nums.Length - 1;i++)
    {
        if(nums[i] - nums[i+1] != -1)
        {
            return nums[i] + 1;
        }
    }

    return nums[nums.Length-1]+1;
}


//高斯求和
public int MissingNumber(int[] nums) {
    int sum = 0;
    for(int i = 0;i<nums.Length;i++)
    {
        sum += nums[i];
    }

    //因为第一个元素为0,所以...
    return nums.Length * (nums.Length+1)/2 - sum;
}


//异或法
public int MissingNumber(int[] nums) {
    int xor = 0;
    int i = 0;
    for(;i<nums.Length;i++)
    {
        //和相同的数异或两次为本身,和0异或为本身
        xor = xor ^ i ^ nums[i];
    }

    return xor ^ i;
}

编写一个程序判断给定的数是否为丑数。

丑数就是只包含质因数 2, 3, 5 的正整数。

示例 1:
输入: 6
输出: true
解释: 6 = 2 × 3
示例 2:
输入: 8
输出: true
解释: 8 = 2 × 2 × 2
示例 3:
输入: 14
输出: false 
解释: 14 不是丑数,因为它包含了另外一个质因数 7。

说明:

1 是丑数。
2 输入不会超过 32 位有符号整数的范围: [−2^31,  2^31 − 1]。


public bool IsUgly(int num) {
    if(num <= 0) return false;
    while(num%2 == 0) num /= 2;
    while(num%3 == 0) num /= 3;
    while(num%5 == 0) num /= 5;

    return num == 1;
}

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。

示例:
输入: 38
输出: 2 
解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。

进阶:
你可以不使用循环或者递归,且在 O(1) 时间复杂度内解决这个问题吗?


//一次过
public int AddDigits(int num) {
    while(num/10 != 0)
    {
        int temp = num;
        num = 0;
        while(temp/10 != 0)
        {
            num += temp % 10;
            temp /= 10;
        }

        num += temp;
    }

    return num;
}


//一脸懵比
public int AddDigits(int num) {
    return (num-1) % 9 + 1;
}

请判断一个链表是否为回文链表。

示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true

进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public bool IsPalindrome(ListNode head) {
        //反转前端链表
        int num = 0;
        ListNode temp = head;
        while(temp != null)
        {
            num++;
            temp = temp.next;
        }
        
        int medioNum = num / 2;
        ListNode preNode = null;
        ListNode curNode = head;
        ListNode startNode = null;
        while(medioNum != 0)//反转前半段链表
        {
            temp = curNode.next;
            curNode.next = preNode;
            preNode = curNode;
            curNode = temp;
            medioNum--;
        }
        //此时,preNode为前半段的头结点,curNode为后半段的头结点
        if(num % 2 == 1)
        {
            //链表为奇数的情况下,中间的结点为公有结点不用检查
            curNode = curNode.next;
        }
        
        while(curNode != null)
        {
            if(curNode.val != preNode.val)
                return false;
            
            curNode = curNode.next;
            preNode = preNode.next;
        }
        
        return true;
        
    }
}


一次过,我都惊呆了,虽然不难。先遍历链表计算链表的长度,反转前半段的链表,然后逐个对比就可以了。


给定一个整数,编写一个函数来判断它是否是 2 的幂次方。

示例 1:
输入: 1
输出: true
解释: 2^0 = 1


public bool IsPowerOfTwo(int n) {
    if(n <= 0) return false;
    return (n & (n-1)) == 0;
}

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k。


示例 1:
输入: nums = [1,2,3,1], k = 3
输出: true
示例 2:
输入: nums = [1,0,1,1], k = 1
输出: true
示例 3:
输入: nums = [1,2,3,1,2,3], k = 2
输出: false


public bool ContainsNearbyDuplicate(int[] nums, int k) {
    Dictionary<int,int> dic = new Dictionary<int,int>();
    for(int i = 0;i<nums.Length;i++)
    {
        if(dic.ContainsKey(nums[i]))
        {
            if(Math.Abs(dic[nums[i]] - i) <= k)
            {
                return true;
            }
            else
            {
                dic[nums[i]] = i;//更新下标位置,前面的的无用啦
            }
        }
        else
        {
            dic.Add(nums[i],i);
        }
    }

    return false;
}

给定一个整数数组,判断是否存在重复元素。

如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

示例 1:
输入: [1,2,3,1]
输出: true
示例 2:
输入: [1,2,3,4]
输出: false
示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true


//标志法
public bool ContainsDuplicate(int[] nums) {
    Dictionary<int,bool> dic = new Dictionary<int,bool>();
    for(int i = 0;i<nums.Length;i++)
    {
        if(dic.ContainsKey(nums[i]))
        {
            return true;
        }
        else
        {
            dic.Add(nums[i],true);
        }
    }

    return false;
}


//排序法
public bool ContainsDuplicate(int[] nums) {
    if(nums.Length == 0 || nums.Length == 1)  return false;
    Array.Sort(nums);
    for(int i = 0;i<nums.Length - 1;i++)
    {
        if(nums[i] == nums[i+1])
        {
            return true;
        }
    }
    return false;
}

反转一个单链表。

示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode ReverseList(ListNode head) {
        
        //用三个指标,一个保存上一个,一个保存当前,一个用来临时保存数据
        ListNode temp = head;
        ListNode preNode = null;
        ListNode curNode = head;
        while(curNode != null)
        {
            temp = curNode.next;
            curNode.next = preNode;
            preNode = curNode;
            curNode = temp;
        }
        
        return preNode;
    }
}

给定两个字符串 s 和 t,判断它们是否是同构的。

如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。

所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

示例 1:
输入: s = "egg", t = "add"
输出: true
示例 2:
输入: s = "foo", t = "bar"
输出: false
示例 3:
输入: s = "paper", t = "title"
输出: true


说明:
你可以假设 和 具有相同的长度。


public bool IsIsomorphic(string s, string t) {
    Dictionary<char,int> dic1 = new Dictionary<char,int>();
    Dictionary<char,int> dic2 = new Dictionary<char,int>();
    int index1 = -1;
    int index2 = -1;

    for(int i = 0;i<s.Length;i++)
    {
        index1 = -1;
        index2 = -1;

        if(dic1.ContainsKey(s[i]))
        {
            index1 = dic1[s[i]];
        }
        else
        {
            dic1.Add(s[i],i);
        }

        if(dic2.ContainsKey(t[i]))
        {
            index2 = dic2[t[i]];
        }
        else
        {
            dic2.Add(t[i],i);
        }

        if(index1 != index2)
        {
            return false;
        }

    }

    return true;
}

删除链表中等于给定值 val 的所有节点。

示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode RemoveElements(ListNode head, int val) {
        
        ListNode MyHead = new ListNode(0);//建一个头结点,应对要删除first结点的情况,达到一致的普遍性
        MyHead.next = head;
        ListNode preNode = MyHead;
        while(head != null)
        {
            if(head.val == val)
            {
                //移除结点,上一个结点不变
                preNode.next = head.next;
            }
            else
            {
                preNode = head;//上一个结点推进
            }
            head = head.next;//日常推进
        }
        
        return MyHead.next;
    }
}