萝卜快跑
萝卜快跑,是百度在 2021 年 8 月推出的,目的是通过百度多年积累的自动驾驶技术,加速全民无人化出行时代的到来。
和常规的网约车不同,萝卜快跑打来的车辆,是没有司机的,乘客落座后,车子会自动规划路线,送乘客到目的地。
布局多年,萝卜快跑真正开始"破圈",被大家所知道,则是这两三个月的事情。
过去几个月,最出彩的萝卜在武汉。
最开始,大概是 6 月中旬的时候,萝卜快跑突发性地有不少负面话题冲上热搜。
一时间,大量「萝卜快跑的车辆,经常引发交通拥堵,为市民的正常通勤带来困扰」这样的言论集中出现。
很快,萝卜的官号就发帖,指出当时的言论都是"水军故意抹黑",目前已配合公安成功侦破。
但你要说,这些负面舆论是不是真的清一色的"水军行为",我看未必。
有水军恶意抹黑或许不假,但据全网这么多网友的体验感受来看,萝卜快跑也确实有"过于谨慎"的问题。例如最高时速不超过 40 公里,遇到马路上的黑色塑料袋,会当成障碍物停下,直到塑料袋飘走...
从技术层面来看,这也很好理解,毕竟萝卜快跑现在做的是 L4 级别的自动驾驶,和我们日常用车中的 L2 辅助驾驶不是一个层级。
一个最简单的区别,在 L2 级别下发生事故,驾驶员负全部责任,系统仅是提供辅助,而在 L4 级别下发生事故,通常由车商或者系统供应商担责。
萝卜快跑跑得慢,但仍被广泛接受,自然也有其自身优点。
其中一个优点:相比于长期以「脾气火爆 + 驾驶彪悍」形象著称的武汉司机来说,萝卜快跑给大家提供了"i人选项",而且该选项从不绕路,比导航软件更知晓路况的拥堵情况,更能做出接近最优的路线选择。
但真正让萝卜快跑实现"绝杀"的是它的价格。
同样是 10 公里的路程,普通网约车价格在 18元30元 之间,而萝卜快跑的价格在 4元16元。
「萝卜快跑的上限价格」就比「普通网约车的下限价格」还低,而且还能 7*24 的接单,这还怎么比?
还有网友分享了自己 2 公里行程的萝卜快跑体验:"乘坐环境舒适,空间大,平时 10 元的打车费用,现在用萝卜快跑,只要 1.55 元,比公交车还便宜"。
不少网友直呼梦回当年滴滴和 Uber 的补贴大战,又一次感受到了打车自由。
诸多的叠加因素,百度进一步铺开了萝卜快跑在武汉的量。
据湖北发布官方信息称,如今武汉市以萝卜快跑为首的无人订单量迎来了爆发式增长。
单日单车峰值超 20 单,已可与出租车司机订单情况达到同一水平。
但随之带来的是"社会稳定性"的问题:网约车行业作为城市的铁人三项之一(另外两个是外卖配送和快递员),创造了无数的就业岗位,同时也是众多人失业后的"理想后路",现在连这个位置也要被机器抢走。
科技抢夺底层人饭碗,这引发了不少的社会恐慌。
甚至连什么「司机一觉醒来天塌了」这样的标题都出来了:
对此交通局回应:行业比较稳定 🤣🤣
我始终觉得,要以未来的眼光去看现在,现在的平台外卖员/网约车司机/电商快递员,在二十年前都不是能够承载这么多就业人数的岗位,甚至于都不存在。
以所谓的「抢人类饭碗」为由,来限制行业发展,是短浅的。
我们不能只指望央企国企带来创新性,只有像百度、阿里这种量级的民营企业发展好了,我们才有跟别人掰手腕的可能。
我对百度无感,甚至于没少嘲笑它在所有产品上都犯了「起个大早,赶个晚集」的错误。
但我也确实衷心希望萝卜快跑能成,这其实多少关乎于我们能否走出「人口红利」这一蜜糖罐,尤其是在出生率开始明显下降的如今,提高社会人效是一个科学的社会问题。
所谓的「行业集体下岗」这样的论调,我们在滴滴和 Uber 推出的时候就听过,现在得到的结果是,出租车司机不再是一个有门槛的行业,我们有了更多的就业,大家的出行方式更加科学;再往前一点,这样的言论在我国制造业自动化过程中,也听得不少,现在得到的结果是,我们在诸多行业的产能能够直接满足全球需求,Made in China 遍布全球。
所以别怕,只管拥抱变化。
或许在我们可以触摸到的未来,人工司机能够集体坐在空调房,远程接管这些路况复杂的自动驾驶效果不好的订单,花更少的力气来赚差不多的钱。
未来的事,谁知道呢,你又怎么看呢?
...
回归主题。
来一道和「百度一面」相关的题目。
题目描述
平台:LeetCode
题号:581
给你一个整数数组 nums,你需要找出一个连续子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的最短子数组,并输出它的长度。
示例 1:
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
示例 2:
输入:nums = [1,2,3,4]
输出:0
示例 3:
输入:nums = [1]
输出:0
提示:
-
-
-
进阶:你可以设计一个时间复杂度为 的解决方案吗?
双指针 + 排序
最终目的是让整个数组有序,那么我们可以先将数组拷贝一份进行排序,然后使用两个指针 i 和 j 分别找到左右两端第一个不同的地方,那么 这一区间即是答案。
Java 代码:
class Solution {
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
int[] arr = nums.clone();
Arrays.sort(arr);
int i = 0, j = n - 1;
while (i <= j && nums[i] == arr[i]) i++;
while (i <= j && nums[j] == arr[j]) j--;
return j - i + 1;
}
}
C++ 代码:
class Solution {
public:
int findUnsortedSubarray(vector<int>& nums) {
int n = nums.size();
vector<int> arr(nums);
sort(arr.begin(), arr.end());
int i = 0, j = n - 1;
while (i <= j && nums[i] == arr[i]) ++i;
while (i <= j && nums[j] == arr[j]) --j;
return j - i + 1;
}
};
Python 代码:
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
n = len(nums)
arr = sorted(nums)
i, j = 0, n - 1
while i <= j and nums[i] ==arr[i]:
i += 1
while i <= j and nums[j] == arr[j]:
j -= 1
return j - i + 1
TypeScript 代码:
function findUnsortedSubarray(nums: number[]): number {
const n: number = nums.length;
const arr: number[] = Array.from(nums).sort((a, b) => a - b);
let i: number = 0, j: number = n - 1;
while (i <= j && nums[i] === arr[i]) i++;
while (i <= j && nums[j] === arr[j]) j--;
return j - i + 1;
};
- 时间复杂度:
- 空间复杂度:
双指针 + 线性扫描
另外一个做法是,我们把整个数组分成三段处理。
起始时,先通过双指针 i 和 j 找到左右两次侧满足 单调递增 的分割点。
即此时 和 满足升序要求,而中间部分 不确保有序。
然后我们对中间部分 进行遍历:
- 发现 :由于对 部分进行排序后 会出现在 后,将不满足整体升序,此时我们需要调整分割点 的位置;
- 发现 :由于对 部分进行排序后 会出现在 前,将不满足整体升序,此时我们需要调整分割点 的位置。
一些细节:在调整
i和j的时候,我们可能会到达数组边缘,这时候可以建立两个哨兵:数组左边存在一个足够小的数,数组右边存在一个足够大的数。
Java 代码:
class Solution {
int MIN = -100005, MAX = 100005;
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
int i = 0, j = n - 1;
while (i < j && nums[i] <= nums[i + 1]) i++;
while (i < j && nums[j] >= nums[j - 1]) j--;
int l = i, r = j;
int min = nums[i], max = nums[j];
for (int u = l; u <= r; u++) {
if (nums[u] < min) {
while (i >= 0 && nums[i] > nums[u]) i--;
min = i >= 0 ? nums[i] : MIN;
}
if (nums[u] > max) {
while (j < n && nums[j] < nums[u]) j++;
max = j < n ? nums[j] : MAX;
}
}
return j == i ? 0 : (j - 1) - (i + 1) + 1;
}
}
C++ 代码:
class Solution {
public:
int MIN = -100005, MAX = 100005;
int findUnsortedSubarray(vector<int>& nums) {
int n = nums.size();
int i = 0, j = n - 1;
while (i < j && nums[i] <= nums[i + 1]) i++;
while (i < j && nums[j] >= nums[j - 1]) j--;
int l = i, r = j;
int minv = nums[i], maxv = nums[j];
for (int u = l; u <= r; ++u) {
if (nums[u] < minv) {
while (i >= 0 && nums[i] > nums[u]) i--;
minv = i >= 0 ? nums[i] : MIN;
}
if (nums[u] > maxv) {
while (j < n && nums[j] < nums[u]) j++;
maxv = j < n ? nums[j] : MAX;
}
}
return j == i ? 0 : (j - 1) - (i + 1) + 1;
}
};
Python 代码:
class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
n, MIN, MAX = len(nums), -100005, 100005
i, j = 0, n - 1
while i < j and nums[i] <= nums[i + 1]:
i += 1
while i < j and nums[j] >= nums[j - 1]:
j -= 1
l, r = i, j
minv, maxv = nums[i], nums[j]
for u in range(l, r + 1):
if nums[u] < minv:
while i >= 0 and nums[i] > nums[u]:
i -= 1
minv = MIN if i < 0 else nums[i]
if nums[u] > maxv:
while j < n and nums[j] < nums[u]:
j += 1
maxv = MAX if j >= n else nums[j]
return 0 if j == i else (j - 1) - (i + 1) + 1
TypeScript 代码:
function findUnsortedSubarray(nums: number[]): number {
const n: number = nums.length, MIN: number = -100005, MAX: number = 100005;
let i: number = 0, j: number = n - 1;
while (i < j && nums[i] <= nums[i + 1]) i++;
while (i < j && nums[j] >= nums[j - 1]) j--;
const l = i, r = j;
let minv = nums[i], maxv = nums[j];
for (let u: number = l; u <= r; u++) {
if (nums[u] < minv) {
while (i >= 0 && nums[i] > nums[u]) i--;
minv = i >= 0 ? nums[i] : MIN;
}
if (nums[u] > maxv) {
while (j < n && nums[j] < nums[u]) j++;
maxv = j < n ? nums[j] : MAX;
}
}
return j === i ? 0 : (j - 1) - (i + 1) + 1;
};
- 时间复杂度:
- 空间复杂度: