LeetCode算法题库练习1

1.两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
我通过的代码(C++):

class Solution {
public:
    vector twoSum(vector& nums, int target) {
        vector result(2,0);
        for(int a=0;a

更好的解答(java):
方法一:暴力法。
遍历每个元素 xx,并查找是否存在一个值与 target - xtarget−x 相等的目标元素。

public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}

方法二:一遍哈希表。

public int[] twoSum(int[] nums, int target) {
    Map map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[] { map.get(complement), i };
        }
        map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");
}

2.两数相加

给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
思路:
1.相加的过程中可能存在进位的操作,所以需要采用一个变量carry来记录进位的情况,初始化carry = 0;
2.因为链表的数字是倒着放的,所以相加起来很方便,将两个链表从头到尾一起遍历,如果有值的话就将它们的值相加sum = val1+val2+carry。
3.如果是两个长度不一样的链表,则需要注意将不再继续向后,且让相应位的和为val1+0.
4.carry的更新,carry = sum/10, 而当前节点和 curr->val = sum%10.
5.循环直至l1,l2都为空。
6.遍历完之后如果carry == 1, 新建一个节点存在进位。
我通过的代码:

/**
 * 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) {
        ListNode* p=l1;
        ListNode* q=l2;
        ListNode* result=new ListNode(0);
        ListNode* cur=result;
        int carry=0;
        while(p||q){
            int x=0,y=0,sum=0;
            if(p!=NULL){
                x=p->val;
                p=p->next;
            }
            if(q!=NULL){
                y=q->val;
                q=q->next;
            }
            sum=x+y+carry;
            carry=sum/10;
            cur->next=new ListNode(sum%10);
            cur=cur->next;
        }
        if(carry)
            cur->next=new ListNode(carry);
        return result->next;
    }
    
};

3.无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是子串的长度,"pwke" 是一个子序列,不是子串。

提交的错误代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int max=0,k=0;
        for(int i=0;imax)
                    max=i-k+1;
            }
            
        }
        return max;
    }
};

提交通过的代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int size,max=0,k=0,index;
        size=s.size();
        for(int i=0;imax)
                max=i-k+1;
        }
        return max;
    }
};

4.整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31, 2^31−1]。请根据这个假设,如果反转后整数溢出那么就返回0。

class Solution {
public:
    int reverse(int x) {
        int reverse=0;
        int y=0;
        while(x)
        {
            reverse=reverse*10+y;
            y=x%10;
            x=x/10;
            
        }
        reverse=reverse*10+y;
        return reverse;
        
    }
};

提交错误:


LeetCode算法题库练习1_第1张图片

更改后通过:

class Solution {
public:
    int reverse(int x) {
        long int reverse=0;
        int y=0;
        while(x)
        {
            y=x%10;
            x=x/10;
            reverse=reverse*10+y;
            if(reverse<-2147483648||reverse>2147483647||reverse==2147483647||reverse==2147483647)
            return 0;
        }
        return reverse;
    }
};

5. 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

class Solution {
public:
    string convert(string s, int numRows) {
        string ret;
        int cycle=2*numRows-2;
        int i,j;
        if(numRows==1)
            return s;
        for(i=0;i

11. 盛最多水的容器

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

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

LeetCode算法题库练习1_第2张图片

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

示例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
第一次提交的代码(暴力算法):

class Solution {
public:
    int maxArea(vector& height) {
        int i,j;
        long s=0,max=0;
        for(i=0;ii;j--)
            {
                if(height[i]max)
                    max=s;
            }
        return max;
    }
};

当遇到最后一次算例[15000,14999,14998,14997,14996,14995,14994,14993,....,6014,6013,6012,6011,6010,6009,6008,6007,6006,6005,6004,6003,6002,600... 28895 more chars]时报:超出时间限制

更改通过:

class Solution {
public:
    int maxArea(vector& height) {
        int i=0,j=height.size()-1;
        int s=0;
        while(i

12.整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。


LeetCode算法题库练习1_第3张图片

例如, 罗马数字 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 的范围内。

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

示例 2:
输入: 4
输出: "IV"

示例 3:
输入: 9
输出: "IX"

示例 4:
输入: 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.

示例 5:
输入: 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.

我的沙雕方法:

class Solution {
public:
    string intToRoman(int num) {
        if(num==0) return "0";
        string res;
        while(num)
        {
            if(num>=1000)
            {
               res+="M";
               num-=1000;
            }
            if(num<1000&&num>=900)
            {
                res+="CM";
                num-=900;
            }
            if(num<900&&num>=500)
            {
                res+="D";
                num-=500;
            }
            if(num<500&&num>=400)
            {
                res+="CD";
                num-=400;
            }
            if(num<400&&num>=100)
            {
                res+="C";
                num-=100;
            }
            if(num<100&&num>=90)
            {
                res+="XC";
                num-=90;
            }
            if(num<90&&num>=50)
            {
                res+="L";
                num-=50;
            }
            if(num<50&&num>=40)
            {
                res+="XL";
                num-=40;
            }
            if(num<40&&num>=10)
            {
                res+="X";
                num-=10;
            }
            if(num<10&&num>=9)
            {
                res+="IX";
                num-=9;
            }
            if(num<9&&num>=5)
            {
                res+="V";
                num-=5;
            }
            if(num<5&&num>=4)
            {
                res+="IV";
                num-=4;
            }
            if(num<4&&num>=1)
            {
                res+="I";
                num-=1;
            }     
        } 
        return res;
    }
};

更好的方法:

class Solution {
public:
    string intToRoman(int num) {
        int values[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
        string reps[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        
        string res;
        for(int i=0; i<13; i++){
            while(num>=values[i]){
                num -= values[i];
                res += reps[i];
            }
        }
        return res;
    }
};

13.罗马数字转整数

罗马数字包含以下七种字符: 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。

class Solution {
public:
    int romanToInt(string s) {
        vector roma {"CM","M","CD","D",
                            "XC","C","XL","L",
                            "IX","X","IV","V",
                            "I"};
        
        vector nums {900,1000,400,500,
                          90,100,40,50,
                          9,10,4,5,
                          1};
        int res = 0;
        for(int i = 0;i<13;i++)
        {
            while(s.find(roma[i])!= string::npos)
            {
                s.erase(s.find(roma[i]),roma[i].size());
                res+=nums[i]; 
            }
        }
        return res;
    }
};

136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
我的代码:

class Solution {
public:
    int singleNumber(vector& nums) {     
        int i,aa=0;
        for(i=0;i<=nums.size();++i)
        {
            if(nums[i]!=nums[i+1])
            {
                aa=nums[i];
                break;
            }    
        }
        return nums[i+1]; 
    }
};

网上的答案:一个数字异或它自己结果为0,异或0结果为它自己即a ^ a=0,a ^ 0=a,且异或满足a ^ b ^ c=a ^ (b ^ c)。因此我们可以设置一个ret异或每个数组元素,最后相同的都抵消为0,那个唯一的数字异或0为它自己即为答案。

int singleNumber(vector& nums) {
       int tmp = 0; 
        for(int i = 0;i < nums.size();i++){   
            tmp = tmp ^ nums[i];
        }
        return tmp;
    }

605. 种花问题

假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?能则返回True,不能则返回False。

示例 1:

输入: flowerbed = [1,0,0,0,1], n = 1
输出: True
示例 2:

输入: flowerbed = [1,0,0,0,1], n = 2
输出: False

我的沙雕方法:

class Solution {
public:
    bool canPlaceFlowers(vector& flowerbed, int n) {
        int i,length=0,j=0;
        /**
        数组中只有一个数(只有一个花坛)的情况:
        [1] 1:False
        [1] 0:True
        [0] 1:True
        [0] 0:True
        **/
        if(flowerbed.size()==1)
        {
            if(flowerbed[0]==0)
                return(n<=1);
            else
                return(n<1);
        }
        /**
        更改数组:遇到是1的元素就将前后元素都变为1
        **/
        for(i=0;i=n) return true;
        else return false;
    }
};

你可能感兴趣的:(LeetCode算法题库练习1)