程序员进阶之算法练习(四十八)LeetCode

正文

题目1.两数相加

题目链接
题目大意:
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

题目解析:
经典面试题。
用链表加法,注意进位的考虑,以及边界情况。


class Solution {
public:
   ListNode* addTwoNumbers(ListNode* node1, ListNode* node2) {
       if (!node1) {
           return node2;
       }
       if (!node2) {
           return node1;
       }
       ListNode *cur = NULL, *head = NULL;
       int addition = 0;
       while (node1 || node2) {
           int sum = addition;
           addition = 0;
           if (node1) {
               sum += node1->val;
               node1 = node1->next;
           }
           if (node2) {
               sum += node2->val;
               node2 = node2->next;
           }
           if (sum >= 10) {
               ++addition;
               sum -= 10;
           }
           if (!cur) {
               cur = new ListNode(sum);
               head = cur;
               cur->next = NULL;
           }
           else {
               cur->next = new ListNode(sum);
               cur = cur->next;
               cur->next = NULL;
           }
       }
       if (addition) {
           cur->next = new ListNode(addition);
           cur = cur->next;
           cur->next = NULL;
       }
       return head;
   }
};

题目2.无重复字符的最长子串

题目链接
题目大意:
给出一个字符串str,求出str中最长子串的长度,要求子串里没有重复的字符。

样例:
Example 1:
Input: "abcabcbb"
Output: 3
最长子串是abc,长度是3;

Example 2:
Input: "bbbbb"
Output: 1
最长子串是b,长度是1;(bb的话出现重复的b)

题目解析:
如果没有重复字符的要求,那么str的最长子串就是自己;
基于此要求,我们考虑从左到右遍历字符串求subStr的时候,如果遇到某个字符subStr不存在,那么便把它加入subStr;
如果遇到某个字符是subStr已经有的,那么便把subStr已出现的字符的位置开始,左边的字符全部不要即可。
比如说对于题目的样例1,当我们枚举a/b/c的时候,都是直接加入subStr,得到abc;
当遇到第四个字符a时,把a去掉得到bc,再加入a,得到bca;
重复这个过程到字符串末尾,记录期间每个字符加入后的长度,可以得到满足要求的最长子串长度。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int vis[257] = {0};
        int maxLen = 0, cur = 0;
        for (int i = 0; i < s.length(); ++i) {
            while (vis[s[i]]) {
                vis[s[cur]] = 0;
                ++cur;
            }
            vis[s[i]] = 1;
            maxLen = max(maxLen, i - cur + 1);
        }
        return maxLen;
    }
};

题目3.Z 字形变换

题目链接
题目大意:
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下:

 L   C   I   R
 E T O E S I I G
 E   D   H   N

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);
示例 1:

输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:

输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:

 L     D     R
 E   O E   I I
 E C   I H   N
 T     S     G

题目解析:
方法1:
找规律,模拟;

方法2:
vector暂存;
去掉x坐标的影响,直接计算y的变化。
trick就是nums=1的特殊判断。

这里使用方法2,代码较为直接:

const int N = 50000;

class Solution {
public:
   string ans[N];
   string convert(string s, int numRows) {
       if (numRows <= 1) {
           return s;
       }
       string ret;
       for (int i = 0; i < numRows; ++i) {
           ans[i].clear();
       }
       int y = 0, gap = 1;
       for (int i = 0; i < s.length(); ++i) {
           ans[y].push_back(s[i]);
           y += gap;
           if (y < 0) {
               y = 1;
               gap = 1;
           }
           else if (y >= numRows) {
               y = numRows - 2;
               gap = -1;
           }
       }
       
       for (int i = 0; i < numRows; ++i) {
           ret += ans[i];
       }
       return ret;
   }
   
}leetcode;


题目4.盛最多水的容器

题目链接
题目大意:
给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。

图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:
输入:[1,8,6,2,5,4,8,3,7]
输出:49

题目解析:
暴力,O(N^2);
递增序列优化,常数优化;
面对1,2,3,4这种bad case,还是一样;

一种O(N)的解法如下:
对于数组height[0 ~ (n-1)],假设最左边的数是x,最右边的数是y;
我们容易知道x和y组合形成的池子是width * min(x,y);
假如x<y,那么对于节点x而言,选择节点y组成形成池子已经是最优解;(因为width * height的公式中,width已经是数组最大宽度,height已经是x的最大值)
那么保存完这个计算结果,实际上x已经可以抛弃!这样便减少了(n-1)次运算!
重复以上过程,可以使得算法时间复杂度为O(N);


class Solution {
public:
    int maxArea(vector<int>& height) {
        int ans = 0;
        int left = 0, right = height.size() - 1;
        while (left < right) {
            ans = max(ans, (right - left) * min(height[left], height[right]));
            if (height[left] < height[right]) {
                ++left;
            }
            else {
                --right;
            }
        }
        return ans;
    }
    
}leetcode;

总结

题目1 经典面试题,用来考察候选人的代码功底;
题目2 经典扫描线题目,从左到右遍历数组,记录一些状态以求最优解;
题目3 思维比较敏捷可以用找规律的方式,如果只是为了解决问题可以多用一些空间,直接去掉x坐标的影响;
题目4 也是比较常见的一类题目,暴力的做法比较简单,但是需要思考最优解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350