刷不动的leetcode系列(四)

485 阅读6分钟

51.给定一个整数数组和一个整数 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

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int,int>map;
        for(int i =0; i < nums.size(); i++)
        {
            if(map.count(nums[i])!=NULL&&i-map[nums[i]]<=k) return true;
            map[nums[i]] = i;
        }
        return false;
    }
};

52.给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。

示例 1:

输入: nums = [1,2,3,1], k = 3, t = 0 输出: true

示例 2:

输入: nums = [1,0,1,1], k = 1, t = 2 输出: true

class Solution {
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        set<long> ss;
        long lt=t;
        for(int i=0;i<nums.size();i++){
            if(i>k) ss.erase(nums[i-k-1]);    
            set<long>::iterator it=ss.lower_bound(nums[i]-lt);  
            if(it!=ss.end() && (*it)-nums[i]<=lt) return true;
            ss.insert(nums[i]);
        }
        return false;
    }
};

53.翻转一棵二叉树。

示例:

输入:

 4

/
2 7 / \ /
1 3 6 9

输出:

 4

/
7 2 / \ /
9 6 3 1

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(!root)
            return NULL;
        TreeNode *t;
        t=root->left;
        root->left=invertTree(root->right);
        root->right=invertTree(t);
        return root;
    }
};

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

示例 1:

输入: 1 输出: true 解释: 20 = 1

示例 2:

输入: 16 输出: true 解释: 24 = 16

//先写我ac但是普通的解法
class Solution {
public:
    bool isPowerOfTwo(int n) {
        if(n==0)
            return false;
        while(n!=1)
        {
            if(n%2==0)
                n/=2;
            else
                return false;
        }
        return true;
    }
};
//下面是大佬的一些思路
	首先,若为2的幂级数,则必定为100000...这种格式
    解法1:利用补码等于反码加一的原则,负数为正数的取反加一,由此两者并之后若还是本身的则为幂级数 		return (n>0)&&(n&-n)==n;
    解法2:最大的2的整数次幂必定可以整除比他小的2的幂级数。
    	return (n>0)&&(1<<30)%n==0;
 	解法3:n-1则为..11111,两者并之后若为0则为2的幂级数
		return (n>0)&&(n&(n-1))==0;

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

示例 1:

输入: 1->2 输出: false

示例 2:

输入: 1->2->2->1 输出: true

//贴一个对我很有启发性的代码,真正的节省时间和空间,但是就是针对这道题目的测试例子过不去
class Solution {
public:
    bool isPalindrome(ListNode* head) { 
        
        float s1=0;
        float s2=0;
        long t=1;
        while(head)
        {
            s1=s1*10+head->val;
            s2=s2+t*head->val;
            t*=10;
            head=head->next;
        }
        return s1==s2;
        
    }
};
//贴一个能ac的垃圾代码
class Solution {
public:
    bool isPalindrome(ListNode* head) { 
        
    ListNode* slow = head, *fast = head,  *prev = nullptr;
    while (fast){//find mid node
        slow = slow->next;
        fast = fast->next ? fast->next->next: fast->next;
    }
    while (slow){//reverse
        ListNode* ovn = slow->next;
        slow->next = prev;
        prev = slow;
        slow = ovn;
    }
    while (head && prev){//check
        if (head->val != prev->val){
            return false;
        }
        head = head->next;
        prev = prev->next;
    }
    return true;
        
    }
};

56.给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点 2 和节点 8 的最近公共祖先是 6。

//根据的是
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            while(1)
            {
                if(p->val<root->val&&q->val<root->val)
                    root=root->left;
                else if(p->val>root->val&&q->val>root->val)
                    root=root->right;
                else
                    return root;
                
            }
    
    }
};

57.请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

现有一个链表 -- head = [4,5,1,9],它可以表示为:

示例 1:

输入: head = [4,5,1,9], node = 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val=node->next->val;
        node->next=node->next->next;
    }
};

58.给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram" 输出: true

示例 2:

输入: s = "rat", t = "car" 输出: false

class Solution {
public:
    bool isAnagram(string s, string t) {
        int i=0;
        int res[26]={};
        for(int i=0;i<s.size();i++)
            res[s[i]-'a']++;
        for(int i=0;i<t.size();i++)
            res[t[i]-'a']--;
        for(int i=0;i<26;i++)
            if(res[i])
                return false;
        return true;
        
    }
};

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

示例:

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

//我写的特别菜的循环解决方式
class Solution {
public:
    int addDigits(int num) {
     int sum=0;
        while(1)
        {
            while(num)
            {
                sum+=num%10;
                num/=10;
            }
            num=sum;
            sum=0;
            if(num%10==num)
                return num;
        }
    }
};
//大佬的O(1)时间复杂度的数学解决方式
除了传统的单纯循环,还可以找规律。假如一个三位数'abc',其值大小为s1 = 100 * a + 10 * b + 1 * c,经过一次各位相加后,变为s2 = a + b + c,减小的差值为(s1 -s2) = 99 * a + 9 * b,差值可以被9整除,每一个循环都这样,缩小了9的倍数。当num小于9,即只有一位时,直接返回num,大于9时,如果能被9整除,则返回9(因为不可能返回0也不可能返回两位数及以上的值),如果不能被整除,就返回被9除的余数。

class Solution:
    def addDigits(self, num: int) -> int:
        if num > 9:
            num = num % 9
            if num == 0:
                return 9
        return num
//f(x*10+y)=f(x*9+x+y)=f(x+y), 成立当f(x)= x%9

//ab = a * 10 + b
ab % 9 = (a*9 + a + b) % 9 = (a + b) % 9
abc = a * 100 + b * 10 + c
abc % 9 = ( a*99 + a + b + c) % 9 = (a + b + c) % 9
    return (num-1)%9+1;  -1+1是为了解决num==9的问题              

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

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

示例 1:

输入: 6 输出: true 解释: 6 = 2 × 3

示例 2:

输入: 8 输出: true 解释: 8 = 2 × 2 × 2

class Solution {
public:
    bool isUgly(int num) {
        if(!num)
            return false;
        while(1)
        {
            if(num%2==0)
                num/=2;
            else if(num%3==0)
                num/=3;
            else if(num%5==0)
                num/=5;
            else if(num==1)
                return true;
            else
                return false;
        }
        return false;
    }
};