哈希表的迭代器是一个指针it
class Solution {
public:
vector twoSum(vector& nums, int target) {
int n = nums.size();
//创建哈希表
unordered_map hashtable;
for(int i = 0;i < n;i++)
{
//查
auto it = hashtable.find(target - nums[i]);
//如果find()存在于哈希表,则返回迭代器it,如果不存在则返回表的末尾:hashtable.end()
if(it != hashtable.end()) return {it->second,i};
//哈希表表示为(first second)
//对应(key,value),映射成数组可以理解为(值,下标)
//添加:hashtable[key] = value;
//通过键来查值
hashtable[nums[i]] = i;
}
return {};
}
};
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
//创建一个可以返回listNode*的方法,l1/l2是两条链的头结点指针
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
//创建头尾结点指针,头结点指针负责初始化链和返回链,尾结点负责移动存取(next)
ListNode* head = nullptr;
ListNode* tail = nullptr;
//进位数curry
int curry = 0;
//取数变量n1n2,求和数sum
int n1,n2,sum;
//遍历l1l2,只要其中有一条当前结点不为空仍然继续循环
while(l1 || l2)
{
//取数
n1 = l1 ? l1->val : 0;
n2 = l2 ? l2->val : 0;
//求和
sum = n1 + n2 + curry;
//如果head为空,则初始化,不为空则添加并移动尾结点
if(!head)
{
head = tail = new ListNode(sum % 10);
}
else
{
tail->next = new ListNode(sum % 10);
tail = tail->next;
}
//计算进位值,至少先sum一次才能计算进位,第一次默认为0
curry = sum / 10;
//判断是否为空并移位,如果为空也没关系,上面取数的时候会赋0
if(l1)
{
l1 = l1->next;
}
if(l2)
{
l2 = l2->next;
}
}
//循环结束之后最后还要看是否有进位值(最高位)
if(curry > 0)
{
tail->next = new ListNode(curry);
}
//返回
return head;
}
};
//方法1:类哈希表桶
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//创建桶(数组),设定128个元素对应0-127ASCII码值,全部赋0
vector m(128, 0);
//存最大长度
int maxlen = 0;
//head表示窗口最左边的字母序号:如果出现重复的,比如两个相同的字母a,上一个a在桶里存的m[s[i]]是a+1表示a的下一个位置
//那么第二个a出现时,head就=a+1也就是max(head,m[s[i]]),去除了窗口里上一个a,保证窗口里无重复字母
int head = 0;
//遍历字符串
for (int i = 0; i < s.size(); i++) {
//修改最左边的字母序号head
head = max(head, m[s[i]]);
//当前字母对应的ASCII码桶里存下一个位置(i+1),用于更新head
m[s[i]] = i + 1;
//更新长度
maxlen = max(maxlen, i - head + 1);
}
return maxlen;
}
};
//方法2:哈希集合
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_set hashset;
int len=s.size();
int left=0,maxstr=0;
for(int i=0;i
动态规划,二维数组
class Solution {
public:
string longestPalindrome(string s) {
int len = s.size();
//长度小于2,只有一个字符,单字符是回文的
if(len < 2)
{
return s;
}
//字串从1个字符开始
int maxlen = 1;
//截取开始下标:最后截取的时候用
int begin = 0;
//二维vector数组的创建
/*vector< vector > dp(n, vector(n) );
定义了一个vector容器,
元素类型为vector,
初始化为包含n个vector对象,
每个对象都是一个新创立的vector对象的拷贝,
而这个新创立的vector对象被初始化为包含n个0。*/
vector> dp(len,vector(len));
//i代表左边界,j代表右边界
//对角线ii相当于i=j左边界等于右边界,即为单个字符,所以为true
for(int i = 0;i < len;i++)
{
dp[i][i] = true;
}
//动态规划相当于填写一张二维的表
//而回文子串需要判断s[i]==s[j],如果相等,就要继续判断去掉两边的中间字串是不是回文
//若中间字串长度小于2,也就是等于1,那么必然是回文,也就是(j-1)-(i+1)+1<2
//也就是j-i<3,也可以写成j-i+1<4,理解为:原长度为3或者2或者1,那么必定为回文串
//另外,如果不满足j-i<3,就需要进一步判断字串是不是回文串s[i+1]...s[j-1]
//参考的值dp[i][j]= (s[i]==s[j] &&(s[i+1][j-1] || j-i<3))
//s[i+1][j-1]也就是参考左下角
//而第零列dp[0][0]没有右上角,所以j从1开始,从左向右,i从0开始,从上到下开始判断,
//每次都要先看看左下角
for(int j = 1;j < len;j++)
{
for(int i = 0;i < j;i++)
{
if(s[i] != s[j])
{
dp[i][j] = false;
}
else
{
if(j-i+1 < 4)
{
dp[i][j] = true;
}
else
{
dp[i][j] = dp[i+1][j-1];
}
}
//更新最长子串的头尾下标
if(dp[i][j] && j-i+1 > maxlen)
{
maxlen = j-i+1;
begin = i;
}
}
}
//截取最长字串
s = s.substr(begin,maxlen);
return s;
}
};
class Solution {
public:
string convert(string s, int numRows) {
int n = s.length(), r = numRows;
if (r == 1 || r >= n) {
return s;
}
//每个周期t有r+r-2个字符
int t = r * 2 - 2;
//因为int会去尾,所以需要将长度凑成最长n+t-1,t-1(一个周期-1),不然有些最后一个周期不满的时候会被去尾
//(n + t - 1) / t得周期数,r-1是每个周期占用的列数,得c:矩阵列数
int c = (n + t - 1) / t * (r - 1);
vector mat(r, string(c, 0));
for (int i = 0, x = 0, y = 0; i < n; ++i) {
mat[x][y] = s[i];
//判断下一个位置的走向
//i
// 将数字 digit 推入 rev 末尾rev = rev * 10 + digit
−2^31≤rev*10+digit≤2^31−1 可以推导成 rev < INT_MIN / 10 || rev > INT_MAX / 10
class Solution {
public:
int reverse(int x) {
int rev = 0;
while (x != 0) {
if (rev < INT_MIN / 10 || rev > INT_MAX / 10) {
return 0;
}
int digit = x % 10;
x /= 10;
rev = rev * 10 + digit;
}
return rev;
}
};
class Automaton{
string state = "start";
//用哈希表画了一个字符串映射字符串数组的自动机
unordered_map> table = {
{"start", {"start", "signed", "in_number", "end"}},
{"signed", {"end", "end", "in_number", "end"}},
{"in_number", {"end", "end", "in_number", "end"}},
{"end", {"end", "end", "end", "end"}}
};
//写一个取下标的函数
int getindex(char c)
{
//isspace判断是否是空(空格或者换行符等等都算空)
if(isspace(c)) return 0;
if(c=='+'||c=='-') return 1;
//isdigit判断是否为0-9数字
if(isdigit(c)) return 2;
return 3;
}
public:
//符号
int sign = 1;
//long和int一般都是32位(4字节),longlong为64位(8字节)
long long ans = 0;
//写了一个取字符串的字符并进位累加的函数
void get(char c)
{
state = table[state][getindex(c)];
if (state == "in_number") {
//字符串或者字符-'0'代表转string/char转int类型(ascii)
ans = ans * 10 + c - '0';
ans = sign == 1 ? min(ans, (long long)INT_MAX) : min(ans, -(long long)INT_MIN);
}
else if (state == "signed")
sign = c == '+' ? 1 : -1;
}
};
class Solution {
public:
int myAtoi(string s) {
Automaton automaton;
for (char c : s)
automaton.get(c);
return automaton.sign * automaton.ans;
}
};
解法1:取后一半数字和前一半数字比较
class Solution {
public:
bool isPalindrome(int x) {
// 特殊情况:
// 如上所述,当 x < 0 时,x 不是回文数。
// 同样地,如果数字的最后一位是 0,为了使该数字为回文,
// 则其第一位数字也应该是 0
// 只有 0 满足这一属性
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int revertedNumber = 0;
while (x > revertedNumber) {
revertedNumber = revertedNumber * 10 + x % 10;
x /= 10;
}
// 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。
// 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123,
// 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。
return x == revertedNumber || x == revertedNumber / 10;
}
};
解法2:整数反转(挺快的)
利用第7题的溢出控制 完成整数反转比较原数
当然也可以直接longlong防止溢出(doge)
class Solution {
public:
bool isPalindrome(int x) {
int temp = x;
if(x<0 ||(x%10==0&&x!=0)) return false;
int rev = 0;
while (x != 0) {
if (rev < INT_MIN / 10 || rev > INT_MAX / 10) {
return 0;
}
int digit = x % 10;
x /= 10;
rev = rev * 10 + digit;
}
return rev==temp;
}
};
朋友分享的美团javascript一面面试题,这边给一个c++解和一个javascript解
大意是给你个数组,让你返回一个连续的最长非严格递增子序列数组
vector ans;
int head, tmp, tail;
vector numarr = { 37,2,3,4,4,9 };
//用哈希表管理用三指针遍历时遇见的所有连续递增下标,key是头,value就是尾
unordered_map hashtable;
int maxkey = 0;
int maxvalue = 0;
int len = numarr.size();
void printArray(vector &numarr,vector &ans)
{
//三指针
head = 0;
tmp = 0;
tail = 0;
hashtable[0] = 0;
while (tail < len-1)
{
tail++;
if (numarr[tail] > numarr[tmp])
{
tmp++;
hashtable[head] = tail;
}
else
{
tmp=tail;
head=tail;
hashtable[head] = tail;
}
}
for (auto a : hashtable)
{
int key = a.first;
int value = a.second;
if (value - key + 1 > maxvalue - maxkey + 1)
{
maxvalue = value;
maxkey = key;
}
}
for (int i = 0; i < maxvalue - maxkey+1; i++)
{
cout << numarr[maxkey+i];
}
}
贪心算法javascript
var findLengthOfLCIS = function(nums) {
let maxhead = 0;
let maxtail = 0;
let ans = 0;
const n = nums.length;
let start = 0;
for (let i = 0; i < n; i++)
{
if (i > 0 && nums[i] <= nums[i - 1])
{
start = i;
}
if (ans < i - start + 1)
{
ans = i - start + 1;
maxhead = start;
maxtail = i;
}
}
var arr = new Array();
for (let i = 0; i < ans; i++)
{
arr[i] = nums[maxhead+i];
}
return arr;
};