[日常刷题]leetcode第十七天

版权声明:希望各位多提意见多多互相交流哦~ https://blog.csdn.net/wait_for_taht_day5/article/details/82861013

189. Rotate Array

Given an array, rotate the array to the right by k steps, where k is non-negative.

Example 1:

Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]

Example 2:

Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation: 
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]

Note:

  • Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
  • Could you do it in-place with O(1) extra space?

Solution in C++:

关键点:

  • 环的性质

思路:

  • 拿到就只有暴力的想法了,看到解析,发现自己的暴力还是稍微优化了一点的,但是又不如第二种用了n个空间的代码来得简便,看的下去的看官,看看吧。大概想法是如果k大于一半则将前面size-k位存下来,将后面k位直接向前移,然后再把存下来的值填入;如果小于一半则后移,存后面k位,将前面size-k位向后移,然后填入
  • 看到这题其实是有想到自己最开始复习考研的时候高分笔记里面有讲过这个,可能不太了解这个的原理是什么,只知道这种方法很神奇。就是reverse(nums, 0 , size-1); reverse(nums, 0, k -1); reverse(nums, k, size-1);
  • 还有一种就是每次将n/k个放入正确的位置,循环k次,大致思路就是用一个tmp存入要存入下个正确位置的值,当这一轮找完之后会回到最开始这个n/k开始的位置,一轮就结束。

方法一: 混合暴力

void rotate(vector<int>& nums, int k) {
        // method 1:bruste
        size_t size = nums.size();
        
        if (k % size == 0)
            return;
        
        if ( k > size)
            k = k % size;
        
        vector<int> tmp;
        
        // 后移
        if (k < size / 2)
        {
            for (int i = size - k; i < size; ++i)
                tmp.push_back(nums[i]);

            for(int i = size - 1; i >= k; --i)
                nums[i] = nums[i - k];

            for (int i = 0; i < k; ++i)
                nums[i] = tmp[i];

        } else{   // 前移
            for (int i = 0; i < size - k; ++i)
                tmp.push_back(nums[i]);

            for(int i = 0;  i + size - k < size; ++i)
                nums[i] = nums[i + size - k];

            for (int i = k; i < size; ++i){
                nums[i] = tmp[i - k];
            }

        }
    }

方法二:循环重置(拿着一个数找到正确位置,然后拿着现在位置的数继续)

size_t size = nums.size();
        k = k % size;
        int count = 0;
        
        for (int start = 0; count < size; ++start )
        {
            int current = start;
            int pre = nums[start];
            do{
                int next = (current + k) % size;
                int tmp = nums[next];
                nums[next] = pre;
                pre = tmp;
                current = next;
                ++count;
            }while(start != current);
        }

方法三:反转

void reverse(vector<int> &nums, int start, int end){
         while(start < end){
             int tmp = nums[start];
             nums[start] = nums[end];
             nums[end] = tmp;
             ++start;
             --end;
         }   
    }
    void rotate(vector<int>& nums, int k) {
		size_t size = nums.size();
        k = k % size;
        reverse(nums, 0, size - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, size - 1);
    }

190. Reverse Bits

Reverse bits of a given 32 bits unsigned integer.
Example:

Input: 43261596
Output: 964176192
Explanation: 43261596 represented in binary as 00000010100101000001111010011100, 
             return 964176192 represented in binary as 00111001011110000010100101000000.

Follow up:
If this function is called many times, how would you optimize it?

Solution in C++:

关键点:

  • 32位二进制数 || 位运算

思路:

  • 十进制转换为二进制存入vector中,这里需要保证转换不足32位时补足,然后直接二进制转十进制即可。这里不用反转,因为存入的过程中是反着存入的。
  • 位运算,没太理解,下次补充

方法一:暴力转换

    // 十进制转二进制
    vector<short> decimalTobinary(uint32_t integer)
    {
        vector<short> result;
        while(integer){
            result.push_back(integer % 2);
            integer /= 2;
        }
        size_t size = result.size();
        if(size < 32)
        {
            for(int i = size; i < 32; ++i)
                result.push_back(0);
        }
        return result;
    }
        
    // 二进制转十进制
    uint32_t binaryTodecimal(vector<short> nums)
    {
        uint32_t result = 0;
        
        for(auto num : nums)
        {
            result = result * 2 + num;
        }
        return result;
    }
    
   uint32_t reverseBits(uint32_t n) {
        return binaryTodecimal(decimalTobinary(n));
    }

方法二:位运算(有两个,估计思想差不多)

 uint32_t reverseBits(uint32_t n) {
        n = ((n & 0x55555555) << 1) | ((n >> 1) & 0x55555555); // swap 2s
        n = ((n & 0x33333333) << 2) | ((n >> 2) & 0x33333333); // swap 4s
        n = ((n & 0x0F0F0F0F) << 4) | ((n >> 4) & 0x0F0F0F0F); // swap 8s
        return (n >> 24) | ((n >> 8) & 0xFF00) | ((n & 0xFF00) << 8) | (n << 24); // swap bytes
    }
    
    uint32_t reverseBits(uint32_t n) {
        n = (n >> 16) | (n << 16);
        n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8);
        n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4);
        n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2);
        n = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1);
        return n;
    }

191. Number of 1 Bits

Write a function that takes an unsigned integer and returns the number of ‘1’ bits it has (also known as the Hamming weight).
Example 1:

Input: 11
Output: 3
Explanation: Integer 11 has binary representation 00000000000000000000000000001011 

Example 2:

Input: 128
Output: 1
Explanation: Integer 128 has binary representation 00000000000000000000000010000000

Solution in C++:

关键点:

  • 位运算

思路:

  • 上面关键点和我的弱鸡方法没有关系,由于上一题的影响,我直接copy了十进制转二进制的代码,改成数1的个数
  • 看了解析,发现还是位运算,定义一个1,然后通过移位和与运算去判断1的个数,和我的方法大同小异
  • 然后后面的改进方法,我不知道是不是真的改进了,可能是对于小的数改进了,通过-1的方法和原数去进行&看是不是0来判断是否前面还有1

方法一:十进制转二进制变种

// 十进制转二进制
    int decimalTobinary(uint32_t integer)
    {
        int result = 0;
        while(integer){
            if(integer % 2 == 1)
                ++result;
            integer /= 2;
        }

        return result;
    }
    
    int hammingWeight(uint32_t n) {
        return decimalTobinary(n);
    }

方法二:位运算比较每位

int hammingWeight(uint32_t n) {
        int k = 1;
        int result = 0;
        for(int i = 0; i < 32; ++i)
        {
            if ((n & k) != 0)  // 注意运算符优先级
                ++result;
            k <<= 1;
        }
        return result;
    }

方法三:方法二针对小数的优化

int hammingWeight(uint32_t n) {
       
        int result = 0;
        while(n)
        {
            ++result;
            n &=(n-1);
        }
        return result;
    }

小结

今天刷题还是很久的。。。调试第一题就调试了很久,i等于多少以及界限问题老是存在一些问题。然后感觉今天主要学习了一些位运算以及第一题中的反转和转换为圈的思路。

知识点

  • 数组右移(反转、转换为圈)
  • 位运算

猜你喜欢

转载自blog.csdn.net/wait_for_taht_day5/article/details/82861013