LeetCode0004

  • 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

  • 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

  • 你可以假设 nums1 和 nums2 不会同时为空。

思路:

  • 时间复杂度若为O(m+n)的话,先确定nums1和nums2是增序还是倒序;
  • 增序的让指针指向头从头到尾读数据,倒序的话让指针指向末尾,从后往前读;
  • 比较当前读到的两个数值,总是优先将小的那个压入临时数组temp;
  • 判断temp个数是奇数还是偶数,返回相应的中位数即可。
//这里我们默认俩数组都是增序,我们先按这个思路提交一下看看是否Accept,测试一下leetcode
var findMedianSortedArrays = function (nums1, nums2) {
//题目设定nums1和nums2不会同时为空
if (nums1) {
if (nums2) {
let i = 0, j = 0, lens1 = nums1.length, lens2 = nums2.length;
let tmp = [];
while (i < lens1 && j < lens2) {
if (nums1[i] < nums2[j]) {
tmp.push(nums1[i]);
i++;
}
else {
tmp.push(nums2[j])
j++;
}
}
if (i < lens1) {
tmp = tmp.concat(nums1.slice(i));
}
if (j < lens2) {
tmp = tmp.concat(nums2.slice(j));
}
let totalLen = lens1 + lens2;
if (totalLen % 2 === 0) {
return (tmp[totalLen / 2 - 1] + tmp[totalLen / 2]) / 2;
}
else {
return tmp[Number.parseInt(totalLen / 2)];
}
}
else {
let lens1 = nums1.length;
if (lens1 % 2 === 0) {
return (nums1[lens1 / 2 - 1] + nums1[lens1 / 2]) / 2;
}
else {
return nums1[Number.parseInt(lens1 / 2)];
}
}
}
else {
let lens2 = nums2.length;
if (lens2 % 2 === 0) {
return (nums2[lens2 / 2 - 1] + nums2[lens2 / 2]) / 2;
}
else {
return nums2[Number.parseInt(lens2 / 2)];
}
}
};

结果:

  • emm,虽然过了,但追求Perfect的我们肯定不能简单的就这么过了。

思路二:

  • 想让时间复杂度为logn,我们一般考虑二分算法。
  • 求中位数,其实就是求第k小的数的一种特殊情况,假设我们要找第k小的数,我们可以每次循环排除掉k/2个数。比较两个数组的第k/2个数字,如果k是奇数,向下取整。
  • 两个有序数组的中位数即为:1、两个数组长度(m+n)为奇数,求第(m+n+1)/2小元素;2、两个数组长度(m+n)为偶数,求第(m+n)/2小、第(m+n)/2+1小数字两者的平均值。
  • 规律:A[1] ,A[2] ,A[3],A[k/2] ... ,B[1],B[2],B[3],B[k/2] ... ,如果 A[k/2]<B[k/2] ,那么A[1],A[2],A[3],A[k/2]都不可能是第k小的数字。
  • 这是因为,在A 数组中,比 A[k/2] 小的数有k/2-1个,而对于B数组而言,已知A[k/2]小于B[k/2],就算除了B[k/2],它前边的数字都比 A[k/2] 小,也只有k/2-1个数,所以比 A[k/2] 小的数字最多有 k/2-1+k/2-1=k-2个,所以 A[k/2] 最多是第 k-1 小的数。而比 A[k/2] 小的数更不可能是第k小的数了,所以可以A[1],A[2]...A[k/2]都排除掉。
  • 我们每次都是取k/2的数进行比较,有时候可能会遇到数组长度小于k/2的时候,此时将箭头指向数组末尾就可以了。采用递归的思路,每次比较min(k/2,len(数组)) 对应的数字,把小的那个对应的数组的数字排除,将两个新数组进入递归,并且k要减去排除的数字的个数。递归终止的条件为k=1或者某一个数组为空,此时找非空数组的第k个值即可。
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
var findMedianSortedArrays = function (nums1, nums2) {
// 题目设定nums1和nums2不会同时为空
let totalLen = (nums1 ? nums1.length : 0) + (nums2 ? nums2.length : 0);
if (totalLen % 2 === 0) {
// 偶数则要返回第K个和第K+1个
// 因为我在函数里使用的是shift和splice操作,会影响源数组
// 所以找出第K个之后,两个数组中最小k个数就已经都被排除掉了
// 想找俩数组中第k+1个,只要在后续的俩数组中找第一个最小数即可
return (findKthNumberArrays(nums1, nums2, totalLen / 2) + findKthNumberArrays(nums1, nums2, 1)) / 2;
}
else {
//奇数直接返回第K个即可
return findKthNumberArrays(nums1, nums2, (totalLen + 1) / 2);
}
}; function findKthNumberArrays(nums1, nums2, k) {
if (k === 1) {
//不可能存在两者都为空的情况
if (nums1 && nums1.length > 0) {
if (nums2 && nums2.length > 0) {
//弹出两者小的那一个,大的那一个要留着以便二次比较
if (nums1[0] > nums2[0]) {
return nums2.shift();
} else {
return nums1.shift();
}
}
else {//nums1不为空,num2为空
return nums1.shift();
}
} else {//nums1为空,nums2不空
return nums2.shift();
}
}
else {
//不可能存在两者都为空的情况
if (nums1 && nums1.length > 0) {
if (nums2 && nums2.length > 0) {
let interval = Math.floor(k / 2);
// 小的那个数组移除掉k/2个数
// 再找新数组中第k-interval小的数即可
// 要注意K/2可能会比数组本身长度大的多,因此数组不一定取得到k/2-1的值,此时取数组最大值即可
let digit1 = interval > nums1.length ? nums1[nums1.length - 1] : nums1[interval - 1];
let digit2 = interval > nums2.length ? nums2[nums2.length - 1] : nums2[interval - 1];
if (digit1 > digit2) {
interval = Math.min(nums2.length, interval);
nums2.splice(0, interval);
return findKthNumberArrays(nums1, nums2, k - interval);
}
else {
interval = Math.min(nums1.length, interval);
nums1.splice(0, interval);
return findKthNumberArrays(nums1, nums2, k - interval);
}
}
else {//nums2为空,返回nums1中第k个即可,因为是有序数组,第k小也就是第k个数前面k个小数要排除掉以便后续操作
let tmp = nums1.splice(0, k);
return tmp[k - 1];
}
}
else {//nums1为空,循环结束,返回num2中第k个即可,与上面nums1一样的操作
let tmp = nums2.splice(0, k);
return tmp[k - 1];
}
}
}

LeetCode0007

  • 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
  • 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
  • 这题目用Javascript做反而凸显不出题目的必要性,因为Number是浮点数,上下限都远大于231,建议用带int类型并且int类型是32位的语言做,如C#。
/**
* @param {number} x
* @return {number}
*/
var reverse = function(x) {
let maxValue = - 1 - (2 << 30);
let minValue = 2 << 30; if (x > 0) {
let strX = x + '';
let arr = [];
for (let lens = strX.length, i = lens - 1; i > -1; i--) {
arr.push(strX[i]);
}
let result = Number.parseInt(arr.join(''));
if (result > maxValue) {
return 0;
}
return result;
} if (x < 0) {
let strX = x + '';
let arr = [];
for (let lens = strX.length, i = lens - 1; i > 0; i--) {
arr.push(strX[i]);
}
let result = 0 - Number.parseInt(arr.join(''));
if (result < minValue) {
return 0;
}
return result;
} return 0;
};

C#版本

public int Reverse(int x)
{
int result = 0;
int remainder = 0;
//int.MaxValue = 2147483647
//int.MinValue = -2147483648
int topLimit = int.MaxValue / 10;//2147483640
int botLimit = int.MinValue / 10;//-2147483640
while (x!=0)
{
remainder = x % 10;
if (result > topLimit || (result == topLimit && remainder > 7)) return 0;
if (result < botLimit || (result == botLimit && remainder < -8)) return 0;
result = result * 10 + remainder;
x /= 10;
} return result;
}

在项目->属性->生成->高级中开启算数“溢出检查”,我们可以省去两层if判断,改用checked关键字来检查溢出,代码可以改成这样:

public class Solution
{
public int Reverse(int x)
{
int result = 0;
int remainder = 0;
while (x != 0)
{
remainder = x % 10;
try
{
result = checked(result * 10 + remainder);
}
catch (OverflowException e)
{
return 0;
}
x /= 10;
} return result;
}
}

参考资料:

LeetCode Day 2的更多相关文章

  1. 我为什么要写LeetCode的博客?

    # 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...

  2. LeetCode All in One 题目讲解汇总(持续更新中...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...

  3. [LeetCode] Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串

    Find the length of the longest substring T of a given string (consists of lowercase letters only) su ...

  4. Leetcode 笔记 113 - Path Sum II

    题目链接:Path Sum II | LeetCode OJ Given a binary tree and a sum, find all root-to-leaf paths where each ...

  5. Leetcode 笔记 112 - Path Sum

    题目链接:Path Sum | LeetCode OJ Given a binary tree and a sum, determine if the tree has a root-to-leaf ...

  6. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  7. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  8. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  9. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  10. Leetcode 笔记 101 - Symmetric Tree

    题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...

随机推荐

  1. 我的第一次JAVA实训——校园公用房管理系统

    老铁们,昨天电脑没电了.这是上周答应的大项目. 别打脸. 详细内容我之后再写,下面是代码地址. Github地址 附:一个寂寞 以上

  2. C语言-字、半字、内存位宽相关

    1.32位系统:32位系统指的是32位数据线,但是一般地址线也是32位,这个地址线32位决定了内存地址只能有32位二进制,所以逻辑上的大小为2的32次方.内存限制就为4G.实际上32位系统中可用的内存 ...

  3. idea指定启动参数、环境变量

    1.  点击Edit Configurations 2 # VM Arguments 是设置的虚拟机的属性 # VM options # 环境变量参数 这里需要指定-D参数 -server -XX:M ...

  4. 计算机网络(4): socket select使用:聊天室模版

    知识点: 如上所示,用户首先将需要进行IO操作的socket添加到select中,然后阻塞等待select系统调用返回.当数据到达时,socket被激活,select函数返回.用户线程正式发起read ...

  5. P3810 【模板】三维偏序(陌上花开)(CDQ分治)

    题目背景 这是一道模板题 可以使用bitset,CDQ分治,K-DTree等方式解决. 题目描述 有 nn 个元素,第 ii 个元素有 a_iai​.b_ibi​.c_ici​ 三个属性,设 f(i) ...

  6. 第一行代码新闻例子报错 Unable to start activity ComponentInfo 原因

    E/AndroidRuntime: FATAL EXCEPTION: main Process: com.timemanager.jason.fragmentbestpractice, PID: 56 ...

  7. python类的继承、多继承及其常用魔术方法

    继承 一个类可以派生出一个子类,这个子类可以使用父类的属性及方法,也可以在父类的基础上添加自己的独特属性或方法.属性和方法的继承的顺序是先从自己开始,找不到再去找父类,父类没有再找父类的父类,其尽头就 ...

  8. 量化投资_关于Multicharts砖型图(传统砖型图和非传统砖型图)最详细的解释_调用篇

    1. 砖图形成数组后,我们再对他们复制到数组中然后再调用出来看一下. 2. 如下是累计只取20个数组大小为例,如果开始阶段数组长度组成初始的Array[20]的长度,然后这个数组的最后一个值填满后,进 ...

  9. 14 微服务电商【黑马乐优商城】:day02-springcloud(理论篇一:HttpClient的简单使用)

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一: ...

  10. 【Java杂货铺】JVM#虚拟机加载机制

    代码编译的结果从本地机器码变为字节码,是储存格式发展的一小步,却是编程语言发展的一大步--<深入理解Java虚拟机> 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转化 ...