#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
struct LinkNode
{
int val_ = 0;
LinkNode* next = nullptr;
LinkNode* random = nullptr;
LinkNode(int val)
{
val_ = val;
}
};
void print(LinkNode* node)
{
while(node != nullptr)
{
cout << node->val_ <<" ";
node = node->next;
}
cout << endl;
}
LinkNode* generateLinkNode(const vector<int>& nums)
{
int n = nums.size();
LinkNode dummy(0);
LinkNode* head = &dummy;
for(int i = 0; i < n; ++i)
{
LinkNode* cur = new LinkNode(nums[i]);
head->next = cur;
head = head->next;
}
return dummy.next;
}
LinkNode* removeElements(LinkNode* head,int val)
{
LinkNode dummy(0);
dummy.next = head;
LinkNode* cur = &dummy;
while(cur->next!=nullptr)
{
if(cur->next->val_ == val)cur->next = cur->next->next;
else cur = cur->next;
}
return dummy.next;
}
LinkNode* removeElements_r(LinkNode* head,int val)
{
if(nullptr == head)return nullptr;
head->next = removeElements_r(head->next,val);
return head->val_ == val ?head->next:head;
}
LinkNode* removeDuplicate(LinkNode* head)
{
LinkNode* cur = head;
while(cur != nullptr)
{
while(cur->next != nullptr && cur->next->val_ == cur->val_)
{
cur->next = cur->next->next;
}
cur = cur->next;
}
return head;
}
LinkNode* removeDuplicate_r(LinkNode* head)
{
if(nullptr == head || nullptr == head->next)return head;
head->next = removeDuplicate_r(head->next);
return head->next->val_ == head->val_ ? head->next:head;
}
LinkNode* deleteDuplicate(LinkNode* head)
{
LinkNode dummy(0);
dummy.next = head;
LinkNode* cur = head;
LinkNode* pre = &dummy;
while(cur != nullptr && cur->next != nullptr)
{
if(cur->val_ == cur->next->val_)
{
int tmp = cur->val_;
while(cur != nullptr && tmp == cur->val_)cur = cur->next;
pre->next = cur;
}
else
{
pre = pre->next;
cur = cur->next;
}
}
return dummy.next;
}
LinkNode* removeNthFromEnd(LinkNode* head,int n)
{
LinkNode dummy(0);
dummy.next = head;
LinkNode* first = &dummy, *second = &dummy;
for(int i = 1; i <= n + 1; ++i)
{
first = first->next;
}
while(first != nullptr)
{
first = first->next;
second = second->next;
}
second->next = second->next->next;
return dummy.next;
}
LinkNode* removeZeroSumSubList(LinkNode* head)
{
int preFix = 0;
LinkNode dummy(0);
dummy.next = head;
unordered_map<int,LinkNode*>map;
map[0] = &dummy;
for(LinkNode* i = &dummy; i != nullptr; i = i->next)
{
preFix+=i->val_;
map[preFix] = i;
}
preFix = 0;
for(LinkNode* i = &dummy;i != nullptr; i = i->next)
{
preFix += i->val_;
i->next = map[preFix]->next;
}
return dummy.next;
}
LinkNode* endOfFirst(LinkNode* head)
{
LinkNode* slow = head;
LinkNode* fast = head;
while(fast->next != nullptr && fast->next->next != nullptr)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
LinkNode* reverse(LinkNode* head)
{
LinkNode* pre = nullptr;
while(head != nullptr)
{
LinkNode* next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
bool isPalindrome(LinkNode* head)
{
LinkNode* firstHead = endOfFirst(head);
LinkNode* second = reverse(firstHead->next);
LinkNode* p1 = head;
LinkNode* p2 = second;
bool result = true;
while(result && p2 != nullptr)
{
if(p1->val_ != p2->val_)return false;
p1 = p1->next;
p2 = p2->next;
}
firstHead->next = reverse(second);
return result;
}
int length(LinkNode* head)
{
int size = 0;
while(head != nullptr)
{
++size;
head = head->next;
}
return size;
}
LinkNode* getInersection(LinkNode* headA, LinkNode* headB)
{
int lenA = length(headA), lenB = length(headB);
while(lenB > lenA)
{
headB = headB->next;
--lenB;
}
while(lenA > lenB)
{
headA = headA->next;
--lenA;
}
while(headA != nullptr&& headB != nullptr)
{
if(headA->val_ == headB->val_)return headA;
headA = headA->next;
headB = headB->next;
}
return nullptr;
}
LinkNode* copyRandom(LinkNode* head)
{
unordered_map<LinkNode* ,LinkNode*>map;
for(LinkNode* i = head; i != nullptr; i = i->next)
{
map[i] = new LinkNode(i->val_);
}
for(LinkNode* cur = head; cur != nullptr; cur = cur->next)
{
map[cur]->next = map[cur->next];
map[cur]->random = map[cur->random];
}
return map[head];
}
LinkNode* reverse(LinkNode* head,LinkNode* newHead)
{
if(nullptr == head)return newHead;
LinkNode* next = head->next;
head->next = newHead;
return reverse(next,head);
}
LinkNode* reverseBetween(LinkNode* head,int m, int n)
{
LinkNode dummy(-1);
dummy.next = head;
LinkNode* pre = &dummy;
LinkNode* cur = dummy.next;
int i = 1;
while(i < m)
{
pre = cur;
cur = cur->next;
++i;
}
LinkNode* node = pre;
while(i ++ <= n)
{
LinkNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
node->next->next = cur;
node->next = pre;
return dummy.next;
}
LinkNode* reverseKGroup(LinkNode* head, int k)
{
LinkNode* node = head;
int cnt = 0;
while(cnt < k)
{
if(nullptr == node)return head;
node = node->next;
++cnt;
}
LinkNode* pre = reverseKGroup(node,k);
while(cnt-- > 0)
{
LinkNode* next = head->next;
head->next = pre;
pre = head;
head = next;
}
return pre;
}
LinkNode* addTwoNumbers(LinkNode* l1, LinkNode* l2)
{
LinkNode dummy(0);
LinkNode* cur = &dummy;
int carry = 0;
while(l1 != nullptr || l2 != nullptr || carry == 1)
{
int sum = (l1 == nullptr ? 0 :l1->val_) + (l2 == nullptr ? 0 : l2->val_) + carry;
cur->next = new LinkNode(sum % 10);
carry = sum / 10;
if(l1!= nullptr)l1 = l1->next;
if(l2!= nullptr)l2 = l2->next;
cur = cur->next;
}
return dummy.next;
}
LinkNode* mergeTwoLists(LinkNode* l1, LinkNode* l2)
{
LinkNode dummy(0);
LinkNode* cur = &dummy;
while(l1 != nullptr && l2 != nullptr)
{
if(l1->val_ < l2->val_)
{
cur->next = l1;
l1 = l1->next;
}
else
{
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = l1 == nullptr ? l2:l1;
return dummy.next;
}
LinkNode* partition(const vector<LinkNode*>& lists,int start, int end)
{
if(start == end)return lists[start];
if(start < end)
{
int mid = start + (end - start) / 2;
auto l1 = partition(lists,start,mid);
auto l2 = partition(lists,mid+1,end);
return mergeTwoLists(l1,l2);
}
return nullptr;
}
LinkNode* mergeKLists(const vector<vector<int>>& lists)
{
vector<LinkNode*>listss;
for(int i = 0; i < lists.size(); ++i)
{
listss.push_back(generateLinkNode(lists[i]));
}
return partition(listss,0,lists.size() - 1);
}
bool hasCycleNode(LinkNode* head)
{
LinkNode* slow = head, *fast = head;
while(fast != nullptr && fast->next != nullptr)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast) return true;
}
return false;
}
LinkNode* detectCycleNode(LinkNode* head)
{
LinkNode* slow = head, *fast = head;
while(fast != nullptr && fast->next != nullptr)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
{
fast = head;
while(fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
}
return nullptr;
}
int findDuplicate(const vector<int>& nums)
{
int slow = nums[0];
int fast = nums[0];
while(true)
{
slow = nums[slow];
fast = nums[nums[fast]];
if(slow == fast)
{
fast = nums[0];
while(fast != slow)
{
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
}
return -1;
}
int main()
{
//LeetCode203
vector<int>nums{1,2,6,3,4,5,6};
int val = 6;
auto node = generateLinkNode(nums);
// print(removeElements(node,val));
print(removeElements_r(node,val));
//LeetCode83
nums = {1,1,2};
node = generateLinkNode(nums);
// print(removeDuplicate(node));
print(removeDuplicate_r(node));
//LeetCode82
nums = {1,2,3,3,4,4,5};
node = generateLinkNode(nums);
print(deleteDuplicate(node));
//LeetCode19
nums = {1,2,3,4,5};
int n = 2;
node = generateLinkNode(nums);
print(removeNthFromEnd(node,n));
//LeetCode1171
nums = {1,2,-3,3,1};
print(removeZeroSumSubList(generateLinkNode(nums)));
//LeetCode234
nums = {1,2,2,1};
cout << isPalindrome(generateLinkNode(nums)) << endl;
//LeetCode160
vector<int>listA{4,1,8,4,5};
vector<int>listB{5,6,1,8,4,5};
cout << getInersection(generateLinkNode(listA),generateLinkNode(listB))->val_ << endl;
//LeetCode206
nums = {1,2,3,4,5};
print(reverse(generateLinkNode(nums)));
print(reverse(generateLinkNode(nums),nullptr));
//LeetCode92
nums = {1,2,3,4,5};
int left = 2, right = 4;
print(reverseBetween(generateLinkNode(nums),left,right));
//LeetCode25
nums = {1,2,3,4,5};
int k = 2;
print(reverseKGroup(generateLinkNode(nums),k));
//LeetCode2
auto l1 = {2,4,3};
auto l2 = {5,6,4};
print(addTwoNumbers(generateLinkNode(l1),generateLinkNode(l2)));
//LeetCode445
l1 = {7,2,4,3};
l2 = {5,6,4};
print(reverse(addTwoNumbers(reverse(generateLinkNode(l1)),reverse(generateLinkNode(l2)))));
//LeetCode21
l1 = {1,2,4};
l2 = {1,3,4};
print(mergeTwoLists(generateLinkNode(l1),generateLinkNode(l2)));
//LeetCode23
vector<vector<int>> lists = {{1,4,5},{1,3,4},{2,6}};
print(mergeKLists(lists));
//LeetCode141
LinkNode n1(3);
LinkNode n2(2);
LinkNode n3(0);
LinkNode n4(-4);
n1.next = &n2;
n2.next = &n3;
n3.next = &n4;
n4.next = &n2;
cout << hasCycleNode(&n1) << endl;
//LeetCode142
cout << detectCycleNode(&n1)->val_ << endl;
//LeetCode287
nums = {1,3,4,2,2};
cout << findDuplicate(nums) << endl;
return 0;
}