面试代码题 可以刷一刷CodeTop
链表是否存在环 给你一个链表的头节点 head ,判断链表中是否有环。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <stdio.h> #include <stdbool.h> struct ListNode { int val; struct ListNode * next ; };bool hasCycle (struct ListNode* head) { struct ListNode * slow = head; struct ListNode * fast = head; do { if (fast == NULL || fast->next == NULL ) { return false ; } slow = slow->next; fast = fast->next->next; } while (slow != fast); return true ; }
C实现
字符串数组去重 将字符串数组中重复的字符串去掉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct string_array { char ** data; int length; };struct string_array delete_repeat_string (struct string_array arr) { char ** p = (char **)malloc (arr.length * sizeof (char *)); memset (p, 0 , arr.length * sizeof (char *)); int index = 0 ; bool find_same_string; for (int i = 0 ; i < arr.length; i++) { find_same_string = false ; for (int j = 0 ; j < i; j++) { if (strcmp (arr.data[i], arr.data[j]) == 0 ) { find_same_string = true ; break ; } } if (!find_same_string) { p[index] = (char *)malloc (strlen (arr.data[i]) + 1 ); strcpy (p[index], arr.data[i]); index++; } } struct string_array ans = {p, index}; return ans; }int main () { char * test[] = {"apple" , "banna" , "apple" , "test" , "test1" , "test2" , "banna" , "test23" , "test2" , "test234" }; struct string_array src = {test, sizeof (test) / sizeof (char *)}; struct string_array res = delete_repeat_string(src); for (int i = 0 ; i < res.length; i++) { printf ("%s\n" , res.data[i]); } return 0 ; }
C实现
二分查找 实现第一个大于等于,最后一个小于等于操作,见博客重载记录 二分查找
流控算法 实现一个简单的check函数,处理函数执行前调用check函数,若TPS超过MAX TPS则返回失败
见博客重载记录 流控算法
比较版本号 165. 比较版本号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Solution { public : vector<int > getVersion (string& version) { vector<int > ans; version.push_back ('.' ); int last_pos = 0 ; int pos; while ((pos = version.find ('.' , last_pos)) != string::npos) { ans.emplace_back (stoi (version.substr (last_pos, pos - last_pos))); last_pos = pos + 1 ; pos = version.find ('.' , last_pos); } return ans; } int compareVersion (string version1, string version2) { vector<int > v1 = getVersion (version1); vector<int > v2 = getVersion (version2); if (v1.size () > v2.size ()) { int padding = v1.size () - v2.size (); for (int i = 0 ; i < padding; i++) { v2.emplace_back (0 ); } } else { int padding = v2.size () - v1.size (); for (int i = 0 ; i < padding; i++) { v1.emplace_back (0 ); } } for (int i = 0 ; i < v2.size (); i++) { if (v1[i] > v2[i]) { return 1 ; } else if (v1[i] < v2[i]) { return -1 ; } } return 0 ; } };
写代码时卡壳了,主要的错误在于: 1:忘记了find的参数原型
1 std::size_t std::__cxx11::string::find (char __c, std::size_t __pos) const noexcept
__c和pos的位置写反了 2:v1 v2都传入了version1
1 2 vector<int > v1 = getVersion (version1); vector<int > v2 = getVersion (version1);
3:没有补齐操作,若共用的部分相等则长度大的版本号更大,忽略了修订号有可能为0的情况,1.0.0与1.0
优化版本1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <bits/stdc++.h> using namespace std;class Solution { public : vector<int > getVersion (string& version) { vector<int > ans; version.push_back ('.' ); int last_pos = 0 ; int pos; while ((pos = version.find ('.' , last_pos)) != string::npos) { ans.emplace_back (stoi (version.substr (last_pos, pos - last_pos))); last_pos = pos + 1 ; pos = version.find ('.' , last_pos); } return ans; } int compareVersion (string version1, string version2) { vector<int > v1 = getVersion (version1); vector<int > v2 = getVersion (version2); int i = 0 ; int j = 0 ; while (i < v1.size () || j < v2.size ()) { int x = 0 ; int y = 0 ; if (i < v1.size ()) { x = v1[i]; i++; } if (j < v2.size ()) { y = v2[j]; j++; } if (x > y) { return 1 ; } if (x < y) { return -1 ; } } return 0 ; } };
对于长度不一致的数组,采用或操作的方式进行循环遍历,减少代码量,思路有点像字符串相加中的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public : string addStrings (string num1, string num2) { int i = num1.length () - 1 ; int j = num2.length () - 1 ; int carry = 0 ; string ans; while ((i >= 0 ) || (j >= 0 ) || (carry > 0 )) { int x = (i >= 0 ) ? num1[i] - '0' : 0 ; int y = (j >= 0 ) ? num2[j] - '0' : 0 ; int sum = x + y + carry; ans.push_back (sum % 10 + '0' ); carry = sum / 10 ; i--; j--; } reverse (ans.begin (), ans.end ()); return ans; } };
优化版本2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Solution { public : int compareVersion (string version1, string version2) { version1.push_back ('.' ); version2.push_back ('.' ); int i = 0 ; int j = 0 ; while (i < version1.length () || j < version2.length ()) { long long x = 0 ; while (i < version1.length ()) { if (version1[i] == '.' ) { break ; } x = x * 10 + version1[i] - '0' ; i++; } long long y = 0 ; while (j < version2.length ()) { if (version2[j] == '.' ) { break ; } y = y * 10 + version2[j] - '0' ; j++; } if (x > y) { return 1 ; } if (x < y) { return -1 ; } i++; j++; } return 0 ; } };
遍历时计算数字大小并比较
字符串最长单词 给定一个字符串数组,求其中有效单词(只能包含字母)的最大长度。示例:[abc abc0 abc–d ab] answer:3
版本1:传统的切割字符串然后计算最大长度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <bits/stdc++.h> #include <string_view> using namespace std;vector<string_view> GetVaildWord (string& s) { vector<string_view> ans; s.push_back (' ' ); string_view str_view (s) ; int last_pos = 0 ; int pos; while ((pos = str_view.find (' ' , last_pos)) != string::npos) { string_view word = str_view.substr (last_pos, pos - last_pos); bool vaild = true ; for (char c : word) { if (!((c >= 'a' && c <= 'z' ) || (c >= 'A' && c <= 'Z' ))) { vaild = false ; break ; } } if (vaild) { ans.emplace_back (word); } last_pos = pos + 1 ; } return ans; }int main () { string str = "abc abc0 abc--d ab" ; auto res = GetVaildWord (str); size_t max_len = 0 ; for (auto word : res) { max_len = max (max_len, word.length ()); } cout << max_len << endl; }
版本2:遍历时计算单词长度并判断单词是否有效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std;int main () { string str = "abc abc0 abc--d ab" ; str.push_back (' ' ); int max_len = 0 ; int len = 0 ; bool vaild = true ; for (char c : str) { if (((c >= 'a' && c <= 'z' ) || (c >= 'A' && c <= 'Z' ))) { len++; } else if (c == ' ' ) { if (vaild) { max_len = max (max_len, len); } len = 0 ; vaild = true ; } else { vaild = false ; } } cout << max_len << endl; }
LRU算法 146. LRU 缓存
使用STL list实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <bits/stdc++.h> using namespace std;class LRUCache { public : LRUCache (int capacity) : capacity_ (capacity), size_ (0 ) {} using kv = pair<int , int >; int get (int key) { if (speed_map_.count (key) == 0 ) { return -1 ; } list<kv>::iterator pos = speed_map_[key]; int value = pos->second; if (pos != data_.begin ()) { data_.erase (pos); data_.emplace_front (key, value); speed_map_[key] = data_.begin (); } return value; } void put (int key, int value) { if (speed_map_.count (key) == 0 ) { if (size_ == capacity_) { speed_map_.erase (data_.back ().first); data_.pop_back (); size_--; } data_.emplace_front (key, value); speed_map_.insert ({key, data_.begin ()}); size_++; } else { list<kv>::iterator pos = speed_map_[key]; pos->second = value; if (pos != data_.begin ()) { data_.erase (pos); data_.emplace_front (key, value); speed_map_[key] = data_.begin (); } } } private : int capacity_; int size_; unordered_map<int , list<kv>::iterator> speed_map_; list<kv> data_; };
注意list删除后相应迭代器也失效了 简单示例:
1 2 3 4 5 6 7 8 9 10 11 #include <bits/stdc++.h> using namespace std;int main () { list<int > head; head.emplace_back (12 ); auto iter = head.begin (); cout << *iter << endl; head.erase (iter); cout << *iter << endl; }
使用自定义双向链表,更新LRU时不需要修改map
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include <bits/stdc++.h> using namespace std;struct ListNode { int key; int value; ListNode* prev; ListNode* next; ListNode () = default ; ListNode (int key1, int value1) : key (key1), value (value1) {} static void InsertNode (ListNode* head, ListNode* node) { node->next = head->next; node->prev = head; head->next->prev = node; head->next = node; } static void DeleteNode (ListNode* node) { node->next->prev = node->prev; node->prev->next = node->next; } };class LRUCache { public : LRUCache (int capacity) : capacity_ (capacity), size_ (0 ) { head_.next = &head_; head_.prev = &head_; } int get (int key) { if (speed_map_.count (key) == 0 ) { return -1 ; } ListNode* node = speed_map_[key]; int value = node->value; if (head_.next != node) { ListNode::DeleteNode (node); ListNode::InsertNode (&head_, node); } return value; } void put (int key, int value) { if (speed_map_.count (key) == 0 ) { if (size_ >= capacity_) { ListNode* node = head_.prev; ListNode::DeleteNode (node); speed_map_.erase (node->key); delete node; size_++; } ListNode* node = new ListNode (key, value); ListNode::InsertNode (&head_, node); speed_map_.emplace (key, node); size_++; } else { ListNode* node = speed_map_[key]; node->value = value; if (head_.next != node) { ListNode::DeleteNode (node); ListNode::InsertNode (&head_, node); } } } ~LRUCache () { while (head_.next != &head_) { ListNode* node = head_.next; ListNode::DeleteNode (node); delete node; } size_ = 0 ; } private : int capacity_; int size_; ListNode head_; unordered_map<int , ListNode*> speed_map_; };
重排链表 143. 重排链表 遇到的问题: 1:面试时根本没想到解法,面试官给出了解法后实现上又出现了一些问题 2:链表反转函数实现受反转链表 II 影响使用了虚拟头节点,却没有真正理解那道题中使用虚拟头节点的意义 3:前半部和后半部的连接没有断开,导致无限循环
美团的面试官都很nice,以后要多刷链表相关的算法题了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Solution { public : ListNode* reverseList (ListNode* head) { ListNode* prev = nullptr ; ListNode* curr = head; ListNode* next; while (curr != nullptr ) { next = curr->next; curr->next = prev; prev = curr; curr = next; } return prev; } ListNode* mergeList (ListNode* node1, ListNode* node2) { ListNode virt_head (-1 ) ; ListNode* node = &virt_head; while (node1 != nullptr || node2 != nullptr ) { if (node1 != nullptr ) { node->next = node1; node = node1; node1 = node1->next; } if (node2 != nullptr ) { node->next = node2; node = node2; node2 = node2->next; } } return virt_head.next; } void reorderList (ListNode* head) { if (head == nullptr || head->next == nullptr ) { return ; } ListNode virt_head (-1 , head) ; ListNode* prev = &virt_head; ListNode* slow = head; ListNode* fast = head; while (fast != nullptr && fast->next != nullptr ) { prev = slow; slow = slow->next; fast = fast->next->next; } prev->next = nullptr ; ListNode* latter_half = reverseList (slow); head = mergeList (head, latter_half); } };
寻找后序遍历的后继节点 先进行分类讨论,处理简单的情况,再单独左子节点情况进行处理 当节点为左子节点且右子节点不为空时,需要想明白后继节点一定是叶子节点,后序遍历的顺序是左右根,那么先持续左再尝试向右,直至叶子节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 struct node { struct node *left; struct node *right; struct node *parent; };struct node *next_postorder (const struct node *node) { if (node->parent == NULL ) { return NULL ; } struct node *node_parent = node->parent; if (node_parent->right == node) { return node_parent; } if (node_parent->right == NULL ) { return node_parent; } struct node *next = node_parent->right; while (next->left != NULL || next->right != NULL ) { while (next->left != NULL ) { next = next->left; } if (next->right != NULL ) { next = next->right; } } return next; }
手写快排 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include <bits/stdc++.h> using namespace std;char get_equal_char (char c) { if (c >= 'a' && c <= 'z' ) { return c - ('a' - 'A' ); } return c; }int compare (char c1, char c2) { c1 = get_equal_char (c1); c2 = get_equal_char (c2); if (c1 > c2) { return 1 ; } if (c1 < c2) { return -1 ; } return 0 ; }int partition (char * str, int start, int end) { char p = str[end]; int slow = start - 1 ; for (int fast = start; fast < end; fast++) { if (compare (str[fast], p) == -1 ) { slow++; char tmp = str[slow]; str[slow] = str[fast]; str[fast] = tmp; } } char tmp = str[slow + 1 ]; str[slow + 1 ] = str[end]; str[end] = tmp; return slow + 1 ; }void quick_sort (char * str, int start, int end) { if (start >= end) { return ; } int p = partition (str, start, end); quick_sort (str, start, p - 1 ); quick_sort (str, p + 1 , end); }void my_sort (char * str, int len) { quick_sort (str, 0 , len - 1 ); }int main () { char test[] = "dcAefgkLG" ; printf ("%s\n" , test); my_sort (test, strlen (test)); printf ("%s\n" , test); }
频率前10的单词 与LeetCode 692. 前K个高频单词 类似 给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。
思路 用map记录各单词的出现次数,而后转到另一个map中,反向遍历,输出出现次数高的单词
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public : vector<string> topKFrequent (vector<string>& words, int k) { map<string, int > ma1; for (string& word : words) { ma1[word]++; } map<int , set<string>> ma2; for (auto & kv : ma1) { ma2[kv.second].emplace (kv.first); } vector<string> ans; for (auto iter = ma2.rbegin (); iter != ma2.rend (); ++iter) { for (const string& str : iter->second) { ans.emplace_back (str); if (ans.size () == k) { return ans; } } } return ans; } };
另一种实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public : using Info = pair<string, int >; vector<string> topKFrequent (vector<string>& words, int k) { unordered_map<string, int > ma; for (string& word : words) { ma[word]++; } vector<Info> vec (ma.begin(), ma.end()) ; auto cmp = [](const Info& info1, const Info& info2) -> bool { return info1.second > info2.second || (info1.second == info2.second && info1.first < info2.first); }; sort (vec.begin (), vec.end (), cmp); int size = min <int >(k, vec.size ()); vector<string> ans (size) ; for (int i = 0 ; i < size; i++) { ans[i] = vec[i].first; } return ans; } };
树的最大权重和 对于一个树,每条边都有一个权重,求根节点到叶子节点的最大权重和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <bits/stdc++.h> using namespace std;struct TreeNode { vector<pair<int , int >> childs; };void dfs (const vector<TreeNode>& nodes, int cur_node, int cur_w, int & max_w) { if (nodes[cur_node].childs.empty ()) { max_w = max (max_w, cur_w); return ; } for (const auto & [next_node, w] : nodes[cur_node].childs) { dfs (nodes, next_node, cur_w + w, max_w); } }int main () { int n, m; cin >> n >> m; vector<TreeNode> nodes (n) ; vector<bool > is_child (n, false ) ; for (int i = 0 ; i < m; i++) { int parent, child, w; cin >> parent >> child >> w; is_child[child] = true ; nodes[parent].childs.emplace_back (child, w); } int root = -1 ; for (int i = 0 ; i < n; i++) { if (is_child[i] == false ) { root = i; break ; } } int ans = -(1 << 30 ); dfs (nodes, root, 0 , ans); cout << ans << endl; }
反转链表 II 反转链表 II
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
思路: 这个题目我之前LeetCode写过故基本思路比较清晰,使用虚拟头节点统一处理,注意左侧节点前继节点,左侧节点,右侧节点,右侧节点后继节点的位置关系即可。==不过问题是需要自己写完整的程序(构建链表,反转链表,输出链表等)==,本来功能实现,样例都没啥问题,但面试官说需要多测试几个样例,便直接复制粘贴语句,但忘了复制构造链表的语句,导致第二个样例反转的链表是第一次样例的结果,使得结果非常诡异。当时以为是我实现有问题,调了10多分钟,刚找到原因的时候面试官结束了面试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public : ListNode* reverseBetween (ListNode* head, int left, int right) { if (left == right || head->next == nullptr ) { return head; } ListNode virt_head (-1 , head) ; ListNode* left_prev = &virt_head; for (int i = 1 ; i < left; i++) { left_prev = left_prev->next; } ListNode* prev = left_prev->next; ListNode* curr = prev->next; ListNode* next; for (int i = left; i < right; i++) { next = curr->next; curr->next = prev; prev = curr; curr = next; } left_prev->next->next = next; left_prev->next = prev; return virt_head.next; } };
之前写的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution { public : ListNode* reverseBetween (ListNode* head, int left, int right) { if (head->next == nullptr ) { return head; } ListNode virt_head (-1 , head) ; ListNode* left_node_prev = &virt_head; for (int i = 1 ; i < left; i++) { left_node_prev = left_node_prev->next; } ListNode* left_node = left_node_prev->next; ListNode* prev = left_node; ListNode* curr = left_node->next; ListNode* next; for (int i = left; i < right; i++) { next = curr->next; curr->next = prev; prev = curr; curr = next; } left_node->next = curr; left_node_prev->next = prev; return virt_head.next; } };
memmove实现 估计是我前面问题答的挺好的(自我感觉),面试官出了一个简单题,实现memmove函数功能,避免src与dst重叠时错误的内存拷贝,但我把这个问题想复杂了,以为是什么判断区间重叠之类的问题,并且很久我都没有get到src与dst区间重叠会出现啥问题(有可能面试写代码有点紧张),导致我40分钟都没有写出一个简单题,难顶
相关博客仰视源码,实现memmove
实际上这就是一个简单的分类讨论,只在dst大于src且有重叠区域时需要逆序拷贝,其余情况都要memcpy就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <string.h> #include <stdio.h> void * my_memmove (void * dst, void * src, size_t cnt) { char * dest = (char *)dst; char * source = (char *)src; if (dest < source || dest > source + cnt) { memcpy (dest, source, cnt); } else { for (int i = cnt - 1 ; i >= 0 ; i--) { dest[i] = source[i]; } } return dst; }int main () { char data[20 ]; for (int i = 0 ; i < 20 ; i++) { data[i] = 'a' + i; } char * src = &data[0 ]; char * dest = &data[5 ]; printf ("src content\n" ); for (int i = 0 ; i < 10 ; i++) { printf ("%c " , src[i]); } printf ("\ndest content\n" ); for (int i = 0 ; i < 10 ; i++) { printf ("%c " , dest[i]); } printf ("\ncall memmove\n" ); my_memmove(dest, src, 10 ); printf ("dest content\n" ); for (int i = 0 ; i < 10 ; i++) { printf ("%c " , dest[i]); } }
无重复字符的最长子串 给定一个字符串 s ,请你找出其中不含有重复字符的 最长连续子字符串 的长度。
思路:刚开始想用下一个相同元素位置的方法,以为是优化的方法,后面想想有点问题,就用最简单的set计算无重复字符串的子串长度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public : int lengthOfLongestSubstring (string s) { int ans = 0 ; int start = 0 ; unordered_set<char > tmp; for (int i = 0 ; i < s.length (); i++) { if (tmp.count (s[i]) == 0 ) { tmp.emplace (s[i]); } else { ans = max <int >(ans, tmp.size ()); while (s[start] != s[i]) { tmp.erase (s[start]); start++; } start++; } } ans = max <int >(ans, tmp.size ()); return ans; } };
连续的子数组和
思路:在写的时候使用了前缀和的方式便于计算连续子数组和,但没想到使用map计算余数为x的序号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public : bool checkSubarraySum (vector<int >& nums, int k) { map<int , int > tmp; long long sum = 0 ; tmp.emplace (0 , -1 ); for (int i = 0 ; i < nums.size (); i++) { sum += nums[i]; sum = ((sum % k) + k) % k; if (tmp.count (sum) != 0 ) { if (i - tmp[sum] >= 2 ) { return true ; } } else { tmp.emplace (sum, i); } } return false ; } };
字符串中不同单词的数目(不区分大小写) 使用status遍历记录当前遇到英文字符状态,遍历时顺带将小写字母转换为大写字母,使用set记录不同单词的数目
IP点分地址转换成数字 需同时判断IP地址是否合法,存在其他字符
① 使用状态机遍历字符串(例如:状态1 预期遇到空格 点号 数字,状态2 预期遇到数字 状态3 预期不遇到任何字符)
② 首先将IP地址按点号分割,而后进行处理
相似题目:[编程题]整数与IP地址间的转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <iostream> #include <string> #include <vector> #include <cmath> using namespace std;vector<string> SplitStr (string& s) { s.push_back ('.' ); vector<string> ans; int last_pos = 0 ; int pos; while ((pos = s.find ('.' , last_pos)) != string::npos) { ans.emplace_back (s.substr (last_pos, pos - last_pos)); last_pos = pos + 1 ; } return ans; }int main () { string s; while (cin >> s) { if (s.find ('.' ) != string::npos) { vector<string> nums = SplitStr (s); long long int value = 0 ; for (string& num : nums) { value = value * 256 + atoi (num.c_str ()); } cout << value << endl; } else { long long int value = atol (s.c_str ()); for (int i = 3 ; i > 0 ; i--) { cout << value / (long long int )pow (256 , i); cout << "." ; value %= (long long int )pow (256 , i); } cout << value << endl; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 相关函数方法#include <iostream> #include <algorithm> #include <string> using namespace std;int main () { string s = "ABCDEFG" ; string result; transform (s.begin (), s.end (), s.begin (), ::tolower); cout << s << endl; return 0 ; }int atoi (const char *__nptr) long atol (const char *__nptr) std::string to_string (int __val) int std::__cxx11::stoi (const std::string &__str, std::size_t *__idx = (std::size_t *)0 , int __base = 10 )