两数之和
题目描述:[简单]
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 :
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因 nums[0] + nums[1] == 9 ,则返回 [0, 1] 。
C语言
系统默认代码块:
/**
1. Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
}
系统给出了4个参数,分别是 nums[](整数数组),numsize(该整数数组的个数),target(整数目标值,即两数之和),returnSize[](返回数组下标的个数)。
其中,returnSize一直困扰了我很久,我以为是将返回的数组下标放在这里面,因为看他也是个数组hhh。后来才知道是个数,那就是默认是2嘛。但是很有意思的是,我们一开始很容易把这个赋值写在if里面,其实是增加了时间复杂度的,放在外面不影响最后的测试,但是会在一定程度减少时间复杂度。
第一种思路:for + if 直接干+数组
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
static int arr[2] = {
0};
*returnSize = 2;
for(int i = 0 ; i < numsSize - 1; i++){
for(int j = i+1 ; j < numsSize ; j++){
if(nums[i] + nums[j] == target ){
arr[0] = i;
arr[1] = j;
return arr;
}
}
}
return 0;
}
用两个for对nums数组进行遍历,一开始我用的是:
for(int j = 1 ; j < numsSize ; j++)
那么在下一步if的时候,在判断语句那要加上 i != j 来甄别是否重复情况。增加了时间复杂度。如果变成
for(int j = i+1 ; j < numsSize ; j++)
就不用判断数组元素是否重复的情况。
————更新
可以用malloc动态分配内存,但是时间复杂度其实没有之前低。使用时注意malloc返回的是void\ *类型,但是题目要求int*,那么要进行强制转换,由于该数组只有两个元素,那么分配 int *2个空间,即
int* twoSum(int* nums, int
numsSize, int target, int* returnSize){
int* arr = NULL;
*returnSize = 2;
for(int i = 0 ; i < numsSize - 1; i++){
for(int j = i+1 ; j < numsSize ; j++){
if(nums[i] + nums[j] == target ){
arr = (int*) malloc(sizeof(int)*2);
arr[0] = i;
arr[1] = j;
return arr;
}
}
}
return 0;
}
C++
系统默认代码块:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
}
};
解题代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int i , j;
for(i = 0 ; i < nums.size() - 1 ; i++){
for(j = i+1 ;j < nums.size() ; j++){
if (nums[i] + nums[j] == target)
return {
i , j };
}
}
return {
i , j };
};
};
其中,通过调用nums.size()可以获得数组的个数。而且这里的默认没有returnSize,可以直接return { i , j }; 不过时间复杂度比起c确实高了不少。
回文数
题目描述[简单]:
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入:x = 0
输出:true
C++
系统默认代码块:
class Solution {
public:
bool isPalindrome(int x) {
}
};
首先,本题没有限制是三位数,说明我们所有情况都要考虑到。那么对于负数,很显然因为负号的关系,不可能是回文数。那么我们一开始就要把他们区分开。
所有个位数为0的数字,反过来之后,都不是回文数,因为前面的0会省略到,但是注意一种特殊情况,0是回文数。
class Solution {
public:
bool isPalindrome(int x) {
if(x < 0 || (x % 10 == 0 && x != 0)){
return false;
}
int num = 0 ;
while(x > num){
num = num * 10 + x % 10 ;
x/=10;
}
if (x == num || x == (num / 10) ){
return true;
}
return NULL;
}
};
我采用的是只翻转一半,那么在while里面,只有原数小于翻转的数字,就可以停止翻转了。
对于数字从前看和从后看,要分奇数位和偶数位,如果是奇数位,那么最中间的那位可以不用反转,因为自己跟自己比肯定是一样的。所以在最后我们判断的条件分为两种,如果是奇数位我们要/10使得最中间那位数被消除掉,再比较是否相等。如果是偶数位,就可以直接判断。
C语言
bool isPalindrome(int x){
if(x < 0 || (x % 10 == 0 && x != 0)){
return false;
}
int num = 0 ;
while(x > num){
num = num * 10 + x % 10 ;
x/=10;
}
if (x == num || x == (num / 10) ){
return true;
}
return NULL;
}
罗马数字转整数
题目说明[简单]:
罗马数字包含以下七种字符: 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。
给定一个罗马数字,将其转换成整数。
C++
class Solution {
public:
int romanToInt(string s) {
int num=0;
//IV,IX 4,9; XL,XC 40,90;CD,CM 400,900
for(int i=0;i<s.size();i++){
if(s[i]=='V')
num+=5;
if(s[i]=='L')
num+=50;
if(s[i]=='D')
num+=500;
if(s[i]=='M')
num+=1000;
if(s[i]=='I'){
if(s[i+1]=='V'||s[i+1]=='X') //I放在V和X左边,但是同时要-1
num-=1;
else num+=1;
}
if(s[i]=='X'){
if(s[i+1]=='L'||s[i+1]=='C') //X放在L和C左边,同时-10
num-=10;
else num+=10;
}
if(s[i]=='C'){
if(s[i+1]=='D'||s[i+1]=='M') //C放在D和M左边,同时-100
num-=100;
else num+=100;
}
}
return num;
}
};