leetcode中等题

2.两数相加
题目描述:给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
解法:本题的难点在于满十进一的转换,我们的思路是从第二低位开始 p.next.var+=p.var/10;p.var=p%10;

while(p3->next!=NULL){//满十进一
            p3->next->val+=p3->val/R;
            p3->val=p3->val%R;
            p3=p3->next;
        }
       while (p3->next == NULL && p3->val >= R) {//最高位是大于10的数
            p3->next = new ListNode(p3->val / R);
            p3->val %= R;
            p3 = p3->next;
        }

总体代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        static const int R=10;
        ListNode *p1,*p2,*p3,*h3,*t3;
        p1=l1;
        p2=l2;
        h3=t3=NULL;
        //开加
        while(p1&&p2){
            p3=new ListNode(p1->val+p2->val);
            if(t3==NULL){
                h3=t3=p3;
            }else{
                t3->next=p3;
                t3=p3;
            }
            p1=p1->next;
            p2=p2->next;
        }
        while(p1){
            t3->next=p1;
            t3=t3->next;
            p1=p1->next;

        }
        while(p2){
            t3->next=p2;
            t3=t3->next;
            p2=p2->next;

        }
        p3=h3;
        while(p3->next!=NULL){//满十进一
            p3->next->val+=p3->val/R;
            p3->val=p3->val%R;
            p3=p3->next;
        }
       while (p3->next == NULL && p3->val >= R) {//最高位是大于10的数
            p3->next = new ListNode(p3->val / R);
            p3->val %= R;
            p3 = p3->next;
        }
        return h3;
    }
};

3.无重复字符的最长字符串
题目描述:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
解法:

#include <stdio.h>
#include <string.h>
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int max_line=0;
        int i=0;
        for(int j=0;j<s.size();j++){
            for(int k=i;k<j;k++){
                if(s[k]==s[j]){
                    i=k+1;
                    break;
                }

            }
            if(j-i+1>max_line){
                max_line=j-i+1;
            }
        }
        return max_line;
    }
};

5.最长回文串
题目描述:输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
解法:动态规划:设当前字符为中心字符,分别比较当前值左边和右边的字符是否相同,如果相同则将当前的三个字符设为中心字符,继续左向和右向比较。
有一个小小的bug就是当给定字符有“bb”这种子串时,我们利用相同的思路将“bb"设为中心字符。

#include <string>
using std::string;
class Solution {
public:
    string longestPalindrome(string s) {
        string res="";
        int max_line=0;
        int center=1;
       for(int center=0;center<s.size();center++){//不存在两个连续的字符
           findPal(s,center-1,center+1,res,max_line);
       }
       return res;
    }
private:
    void findPal(string s,int cen_left,int cen_right,string &res,int &max_line){
        while(cen_left>=0&&s[cen_left]==s[cen_left+1]){//左边与中间相同
            cen_left--;
        }
        while(cen_right<s.size()&&s[cen_right]==s[cen_right-1]){//右边与中间相同
            cen_right++;
        }
        while(cen_left>=0&&cen_right<s.size()&&s[cen_left]==s[cen_right]){
            cen_left--;
            cen_right++;
        }
        if(cen_right-cen_left-1>max_line){
            max_line=cen_right-cen_left-1;
            res=s.substr(cen_left+1,max_line);
        }
    }
};

6.Z字变换
题目描述:将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zigzag-conversion
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
解法:找规律,遍历s中每一个字符,分别写入数组row[currentRow]中对应的行中,一旦当前行为第零行或者最后一行时,则改变写入方向;
最后按行读取row就可以了

#include "algorithm"
#include "string"
#include "stdio.h"
class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows==1) return s;

        int len=s.size();
        vector<string> row(min(numRows,len));//避免输入的行数超过字符串的长度

        int currentRow=0;
        bool goingdown=false;//当goingdown为true 向下写入。
        for(char c:s){
            row[currentRow]+=c;
            if(currentRow==0||currentRow==numRows-1){
                goingdown=!goingdown;
            }
            currentRow+=goingdown?1:-1;
        }
        string result;
        for(string row_:row){
            result+=row_;
        }
        return result;
    }
};

11.盛水最多的容器
题目描述:给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

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

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

说明:你不能倾斜容器,且 n 的值至少为 2。

question_11.jpg

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法:1.首先确定最大底,再考虑最大高
2.较低高向较高高移动。


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

12.整数转罗马数字
题目描述:罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内

示例:输入: 3
输出: "III"

解法:官网给的解法是贪心算法,找规律,从最大的罗马数开始比较;

class Solution {
public:
    string intToRoman(int num) {
        int num_[13]={1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};

        string roman[13]={"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
        string result="";

        int index=0;
        while(index<13){

            while(num>=num_[index]){
                result.append(roman[index]);

                num=num-num_[index];

            }

            index++;
        }

        return result;
    }
};

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/integer-to-roman
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

----------------很久没有更新了(主要一边在了解C++的头文件,一边写算法题有一点不舒服,所以打算从现在开始用java写了)------------------

15 三数之和(这个题目与第一题的两数之和有点相似)
题目描述:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法:个人在去重这一方面想了很久也没有想到一个很好的方法去重,看了一个精选的解法才明白。
(1)我们先将这个数组进行排序,排序过后就简化了很多的操作(学到了,以后对数组进行操作时一定先排好序,一下省了太多步骤了)
(2)我们的思路是 先选取一个没有被选取的最小的数A,然后再选定一个最大B的数和除去A以及A之前的数中的最小数C;
如果A+B+C=0,那么恭喜你一个符合标准的数组就选好了。
如果A+B+C>0,那么说明C这个数取大了,则令C等于一个较小的数。
如果A+B+C<0,那么说明B这个数取大了,则令B等于一个较大的数。
如此一来 遍历数组后就可以得到答案

总体代码:

class Solution {
    public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> answer=new ArrayList();
        int len=nums.length;
        if(len<3){//不足三个数
            return answer;
        }
        Arrays.sort(nums);//排序这一步很重要,为之后的去重和结束循环的判断做好了铺垫

        for(int i=0;i<len;i++){
            if(nums[i]>0){
                break;//如果当前数大于0 (此时的当前数z是指三个数中最小的数) 那么就不用继续比较了
            }

            if(i>0&&nums[i]==nums[i-1]) continue;//去重

            int L=i+1,R=len-1;

            while(L<R){
                if((nums[i]+nums[L]+nums[R])==0){//找到了满足条件的一组数
                        answer.add(Arrays.asList(nums[i],nums[L],nums[R]));
                        //接下来就是判断指针的走向了
                        while (L<R && nums[L] == nums[L+1]) L++; // 去重
                        while (L<R && nums[R] == nums[R-1]) R--; // 去重
                        L++;
                        R--;
                }else if((nums[i]+nums[L]+nums[R])<0){
                    //较小的那个匹配数应该变大一些 即L右移
                        L++;
                }else{
                    //较大的那个匹配数左移
                    R--;
                }
            }
        }
        return answer;
    }
}

17.电话号码的字母组合
题目描述:
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

image.png

示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

解法:
1.这种类型的题目第一步当然是做好准备工作,需要将9个数字对应的字符序列先配对起来,这里选用的是键值对的方式使数组和字符的对应。

 //初始化一个hash表
         Map<Character, String> map = new HashMap<Character, String>() {{
            put('2', "abc");
            put('3', "def");
            put('4', "ghi");
            put('5', "jkl");
            put('6', "mno");
            put('7', "pqrs");
            put('8', "tuv");
            put('9', "wxyz");
        }};

2.对于自由组合的题目大多采用递归回溯的方法,这题也不例外
对于实例输入“23”
首先选中2的第一个字符 分别和3的每一个字符配对 配对结束后就回溯的2的第二个字符和3的每一个字符配对。。。依次类推

public void backforword(List<String> combinations,StringBuffer combination,Map<Character, String> map
    ,int index,String digits){
        if(index == digits.length()){
            combinations.add(combination.toString());
        }else{
            char digit=digits.charAt(index);
            String letters=map.get(digit);
            for(int i=0;i<letters.length();i++){
                combination.append(letters.charAt(i));
                backforword(combinations, combination,map,index+1,digits);
                combination.deleteCharAt(index);
            }
        }
    }

完整代码:

class Solution {
    public List<String> letterCombinations(String digits) {
        List<String> combinations=new ArrayList();
        if(digits.length()==0){
            return combinations;
        }
        //初始化一个hash表
         Map<Character, String> map = new HashMap<Character, String>() {{
            put('2', "abc");
            put('3', "def");
            put('4', "ghi");
            put('5', "jkl");
            put('6', "mno");
            put('7', "pqrs");
            put('8', "tuv");
            put('9', "wxyz");
        }};
        StringBuffer combination=new StringBuffer();
        backforword(combinations,combination,map,0,digits);
        return combinations;
    }

    public void backforword(List<String> combinations,StringBuffer combination,Map<Character, String> map
    ,int index,String digits){
        if(index == digits.length()){
            combinations.add(combination.toString());
        }else{
            char digit=digits.charAt(index);
            String letters=map.get(digit);
            for(int i=0;i<letters.length();i++){
                combination.append(letters.charAt(i));
                backforword(combinations, combination,map,index+1,digits);
                combination.deleteCharAt(index);
            }
        }
    }

}

待更。。。。

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

推荐阅读更多精彩内容