48. 旋转图像

给定一个 _n_ × _n_ 的二维矩阵 `matrix` 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 **[原地](https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95)** 旋转图像,这意味着你需要直接修改输入的二维矩阵。**请不要** 使用另一个矩阵来旋转图像。
  • 找到每个点旋转后位置的规律

581. 最短无序连续子数组

给你一个整数数组 `nums` ,你需要找出一个 **连续子数组** ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。

请你找出符合题意的 **最短** 子数组,并输出它的长度。
  • 总结:从左往右,找到比左边最大值还小的最右下标,从右往左,找到比右边最小值还大的最左下标
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int n = nums.size();
        int maxn = INT_MIN, right = -1;
        int minn = INT_MAX, left = -1;
        for (int i = 0; i < n; i++) {
            if (maxn > nums[i]) {
                right = i;
            } else {
                maxn = nums[i];
            }
            if (minn < nums[n - i - 1]) {
                left = n - i - 1;
            } else {
                minn = nums[n - i - 1];
            }
        }
        return right == -1 ? 0 : right - left + 1;
    }
};

41. 缺失的第一个正数

给你一个未排序的整数数组 `nums` ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 `O(n)` 并且只使用常数级别额外空间的解决方案。
  • 这题目的巧妙之处就在于可以修改原来的数组,使得这个数字是多少就直接放到对应的位置就可以了(当然这部分需要循环放置)
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
                swap(nums[nums[i] - 1], nums[i]);
            }
        }
        for (int i = 0; i < n; ++i) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }
        return n + 1;
    }
};

米哈游笔试二题

两个字符串,只能向第一个字符串按顺序插入或者删除m,h,y三个字符,一定是按顺序且插满或者删满三个对应字符,是否最后可以变为第二个字符串
  • 两个字符串删除所有mhy之后是否相等就是结果
  • 删除mhy的方法是使用双栈(先m栈,到h栈)

142. 环形链表 II

给定一个链表的头节点  `head` ,返回链表开始入环的第一个节点。 _如果链表无环,则返回 `null`。_
如果链表中有某个节点,可以通过连续跟踪 `next` 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 `pos` 来表示链表尾连接到链表中的位置(**索引从 0 开始**)。如果 `pos` 是 `-1`,则在该链表中没有环。**注意:`pos` 不作为参数进行传递**,仅仅是为了标识链表的实际情况。
**不允许修改** 链表。
  • 数学问题,龟兔赛跑,快慢指针,指针相遇的位置就是结果的位置

2982. 找出出现至少三次的最长特殊子字符串 II

给你一个仅由小写英文字母组成的字符串 `s` 。
如果一个字符串仅由单一字符组成,那么它被称为 **特殊** 字符串。例如,字符串 `"abc"` 不是特殊字符串,而字符串 `"ddd"`、`"zz"` 和 `"f"` 是特殊字符串。

返回在 `s` 中出现 **至少三次** 的 **最长特殊子字符串** 的长度,如果不存在出现至少三次的特殊子字符串,则返回 `-1` 。

**子字符串** 是字符串中的一个连续 **非空** 字符序列。
  • 隐藏的有点深的差分数组,涉及到数组范围批量更改的都直接上差分数组
    for (int i = 0; i < s.size(); i++) {
      if (i!=0) {
        if (s[i]==s[i-1]) {
          arr[i]=arr[i-1]+1;
        }else {
          arr[i]=1;
        }
      }else {
        arr[i]=1;
      }
      words[s[i]-'a'][1]++;
      words[s[i]-'a'][arr[i]+1]--;
    }

    int result=-1;
    for (auto& word : words) {
      int now=0;
      for (int i = 1; i < word.size(); i++) {
        now+=word[i];
        if (now>=3) {
          result=max(i,result);
        }
      }
    }

995. K 连续位的最小翻转次数

给定一个二进制数组 `nums` 和一个整数 `k` 。
**k位翻转** 就是从 `nums` 中选择一个长度为 `k` 的 **子数组** ,同时把子数组中的每一个 `0` 都改成 `1` ,把子数组中的每一个 `1` 都改成 `0` 。
返回数组中不存在 `0` 所需的最小 **k位翻转** 次数。如果不可能,则返回 `-1` 。
**子数组** 是数组的 **连续** 部分
  • 这题是差分数组,不是很好想,实际上就是走到一个0就翻转,然后到最后康康还有没有剩下的,翻转用的是差分数组
class Solution {
public:
	int minKBitFlips(vector<int>& nums, int k) {
		vector<int> arr(nums.size()+1,0);
		int now=0,result=0;
		for (int i = 0; i< nums.size(); i++) {
			now+=arr[i];
			if (i+k>nums.size()) {
				if ((nums[i]==0&&now%2==0)||(nums[i]==1&&now%2==1)) {
					return -1;
				}
				continue;
			}
			if ((nums[i]==0&&now%2==0)||(nums[i]==1&&now%2==1)) {
				result++;
				now+=1;
				arr[i+k]-=1;
			}
		}
		return result;
	}
};

质数欧拉筛

  • 一种快速找质数的方法,核心方法是使用枚举,将所有质数的倍数都标记为合数,剩下的就是质数
    vector<int> arr(right+1,1);
    arr[1]=0;
    for (long long i = 2; i < right+1; i++) {
      if (arr[i]) {
        for (long long j = i*i; j < right+1; j+=i) {
          arr[j]=0;
        }
      }
    }

牛顿迭代法

  • 设函数f(x)在x0处可导,且f(x)在x0处的一阶导数f′(x0)存在,且f′(x0)≠0,则称x0是方程f(x)=0的一个牛顿迭代点,记作x0∈R,且称函数f(x)在x0处的切线方程为
f(x)=f(x0)+f′(x0)(x−x0)
  • 若x1是方程f(x)=0的一个牛顿迭代点,且x1满足x1=x0−f(x0)f′(x0),则称x1 是方程f(x)=0的一个牛顿迭代点,记作x1∈R,且称函数f(x)在x1 处的切线方程为f(x)=f(x1)+f′(x1)(x−x1)
  • 方程为xn+1=xn−f(xn)f′(xn)
  • 底层是通过切线和x交点越来越接近零点的原理

位运算

136. 只出现一次的数字

给你一个 **非空** 整数数组 `nums` ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
  • 通过两个相同的数字异或为0,0和任何数字异或原来数字不变
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ret = 0;
        for (auto e: nums) ret ^= e;
        return ret;
    }
};

面试

一共N个数,求最大的n个数

  • 将N个数分割分布在每台机器上,使用堆的实现,求出每部分最大的最大n个数字,在进行整合得到最大的n个数

大规模数据去重问题

  • 大部分是直接通过bitmap标识,每个数据占据一个bit,通过01判断是否存在

分布式大量数据下载处理

赛马问题

25匹马,5条赛道,不计时,问至少要赛多少场才能保证找出前三?

  • 7次确实是一定可行的,就25匹马5个一组,比5次,淘汰掉10匹,然后这5次的冠军比一次,获得第4第5的两组全部淘汰(淘汰6匹),第3的组里淘汰2匹,第2的组淘汰1匹,第1的那个确定是所有马里最快的。这样总共已经淘汰了10+6+2+1=19匹,还有1匹确定最快,还剩下5匹比一次就够了。