题目21分析:(调整数组顺序使所有奇数位于所有偶数之前)
考虑时间复杂度问题,可设置首尾第一第二两个指针,当第一指针指向奇数,第二指针指向偶数,则交换指向的数据,
直至第二指针移动到第一指针之前。同时为了考虑算法的可扩展,将奇偶判断写为子函数的形式。
思路:
1.初始化第一指针和第二指针指向数组的首尾
2.轮询第一指针<第二指针
2.向后移动第一指针,直至指向偶数
3.向前移动第二指针,直至指向奇数
4.交换第一、二指针指向的数据
#include <iostream> using namespace std; bool odd_or_even(int num) { if ((num & 0x1) == 0)//奇数的最后一位都是1,所以可利用位与判断数据的奇偶性,偶数==0,奇数==1 return true; else return false; } void reorder_arr(int *arr, int length,bool (*func)(int num))//入口参数是函数名称(也是地址) { if (arr == NULL||length<1) { cout << "数组为空。" << endl; return; } //1.初始化第一指针和第二指针指向数组的首尾 int *first_ptr = arr; int *second_ptr = arr + length - 1; //2.轮询第一指针<第二指针 while (first_ptr < second_ptr) { //2.向后移动第一指针,直至指向偶数 while (first_ptr < second_ptr && !func(*first_ptr))//入口参数 ++first_ptr; //3.向前移动第二指针,直至指向奇数 while (first_ptr < second_ptr&&func(*second_ptr)) --second_ptr; if (first_ptr < second_ptr) { int temp = *first_ptr; *first_ptr = *second_ptr; *second_ptr = temp; } } } void main() { int arr[] = { 1,2,3,4,5 }; int length = sizeof(arr) / sizeof(arr[0]); reorder_arr(arr, length, odd_or_even); for (int i = 0; i < length; i++) cout << arr[i] << endl; }
题目22分析:(链表中倒数第k个节点)
由于是单向链表,如果使用遍历链表两次的方式,时间复杂度较高,所以使用两个指针的方式。保持第一指针和第二指针的距离是k-1,则当第一指针到达尾节点时,第二指针指向的就是倒数第k个节点。思路:
1.初始化第一指针指向头节点、第二指针==NULL
2.首先让第一指针走k-1步,然后让初始化第二指针指向头节点
3.同时向前遍历,直到第一指针到达尾节点
#include <iostream> using namespace std; struct LinkNode { int data; LinkNode *next; }; //创建链表 void create_link(LinkNode *head_ptr, int length) { for (int i = length; i >= 1; --i) { LinkNode *new_node = new LinkNode; new_node->data = i; new_node->next = head_ptr->next; head_ptr->next = new_node; } } //打印链表内容 void print_link(LinkNode *head_ptr, int length) { LinkNode *temp_node = head_ptr->next; while (temp_node!= NULL) { cout << temp_node->data << " "; temp_node = temp_node->next; } cout << endl; } LinkNode* print_tail_k_node(LinkNode *head_ptr, int k) { if (head_ptr == NULL || k == 0) return NULL; //1.初始化第一指针指向头节点、第二指针==NULL LinkNode *first_ptr = head_ptr->next; LinkNode *second_ptr = NULL; //2.首先让第一指针走k-1步,然后让初始化第二指针指向头节点 for (int i = 0; i < k - 1; i++) { if (first_ptr->next != NULL)//防御链表长度小于k的情况 first_ptr = first_ptr->next; else return NULL; } second_ptr = head_ptr->next; //3.同时向前遍历,直到第一指针到达尾节点 while (first_ptr->next != NULL) { first_ptr = first_ptr->next; second_ptr = second_ptr->next; } return second_ptr; } void main() { LinkNode *head_ptr = new LinkNode; head_ptr->data = 0; head_ptr->next = NULL; create_link(head_ptr, 6); print_link(head_ptr, 6); LinkNode *tail_k_node = print_tail_k_node(head_ptr, 3); cout << tail_k_node->data << endl; }
题目23分析:(链表中环的入口节点)
首先需两个快慢指针判断是否有环,如果有环则获得相遇节点,此节点一定在环内;然后获得环中节点的数量n;最终使用两个指针,从头节点开始,第一节点先走n步,然后同时开始移动,直至相遇。
思路:
1.初始化快慢指针,慢指针走一步,快指针走两步,直至相遇返回指针指向节点,否则当慢指针为空时,
则无环,返回NULL
2.获得相遇节点,从此节点开始遍历,直至再次相遇,获得节点数量n
3.初始化第一二指针,移动第一指针n步
4.同时移动第一、二指针,直至相遇
#include <iostream> using namespace std; struct LinkNode { int data; LinkNode *next; }; //创建有环链表 void create_link(LinkNode *head_ptr, int length, int start, int end) { for (int i = length; i >= 1; --i) { LinkNode *new_node = new LinkNode; new_node->data = i; new_node->next = head_ptr->next; head_ptr->next = new_node; } LinkNode *entry_node=NULL; LinkNode *node = head_ptr->next; for (int i = 1; i <= length; ++i) { if (i == end) entry_node = node; if (i == start) node->next = entry_node; if(i!=length) node = node->next; } } //打印链表内容 void print_link(LinkNode *head_ptr, int length, int start, int end) { LinkNode *temp_node = head_ptr->next; int num = 1; while (temp_node != NULL&& num<=10) { cout << temp_node->data << " "; temp_node = temp_node->next; ++num; } cout << endl; } LinkNode *get_meet_node(LinkNode *head_ptr) { //if (head_ptr->next = NULL) // return NULL; //1.初始化快慢指针 LinkNode *slow_node = head_ptr->next; if (slow_node == NULL) return NULL; LinkNode *fast_node = slow_node->next; //有环则不会为空 while (fast_node != NULL&&slow_node != NULL) { //直至相遇返回指针指向节点 if (fast_node == slow_node) return fast_node; //慢指针走一步,快指针走两步 slow_node = slow_node->next; fast_node = fast_node->next; if(fast_node!=NULL) fast_node = fast_node->next; } return NULL;//无环则为空 } LinkNode *get_entry_node(LinkNode *head_ptr) { //2.获得相遇节点,从此节点开始遍历,直至再次相遇,获得节点数量n LinkNode *meet_node = get_meet_node(head_ptr); cout << "相遇节点:" << meet_node->data << endl; if (meet_node == NULL)//无环 return NULL; int num = 1; LinkNode *node = meet_node; while (meet_node != node->next) { node = node->next; ++num; } cout << "环中节点数量:" << num << endl; //3.初始化第一二指针,移动第一指针n步 LinkNode *first_node = head_ptr->next; LinkNode *second_node = head_ptr->next; for (int i = 0; i < num; i++) first_node = first_node->next; //4.同时移动第一、二指针,直至相遇 while (first_node != second_node) { first_node = first_node->next; second_node = second_node->next; } return first_node; } void main() { LinkNode *head_ptr = new LinkNode; head_ptr->next = NULL; create_link(head_ptr, 6, 6, 3); print_link(head_ptr, 6, 6, 3); LinkNode *entry_node = get_entry_node(head_ptr); cout << "环的入口节点是:" << entry_node->data << endl; }